//
#include "pch.h"
-#include "BlankPage.xaml.h"
+#include "App.xaml.h"
+#include "MainPage.xaml.h"
using namespace ShootingGame;
using namespace Platform;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::UI::ViewManagement;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::UI::Xaml::Media::Animation;
+using namespace Windows::Graphics::Display;
+
// The Split Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234228
//TODO: Load state from previously suspended application
}
- // Create a Frame to act navigation context and navigate to the first page
- auto rootFrame = ref new Frame();
- TypeName pageType = { BlankPage::typeid->FullName, TypeKind::Metadata };
- rootFrame->Navigate(pageType);
+ auto mainPage = ref new MainPage();
// Place the frame in the current Window and ensure that it is active
- Window::Current->Content = rootFrame;
+ Window::Current->Content = mainPage;
+ Window::Current->Activated += ref new WindowActivatedEventHandler(this, &App::OnWindowActivationChanged);
Window::Current->Activate();
+
+ simpleSprites_ = ref new SimpleSprites();
+ simpleSprites_->Initialize(Window::Current->CoreWindow,mainPage,DisplayProperties::LogicalDpi);
+
+ eventToken_ =
+ CompositionTarget::Rendering::add
+ (ref new EventHandler<Object^>(this, &App::OnRendering));
+ ApplicationView::GetForCurrentView()->ViewStateChanged +=
+ ref new TypedEventHandler<ApplicationView^, ApplicationViewStateChangedEventArgs^>(
+ this,
+ &App::OnViewStateChanged
+ );
+
+ CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
+ CoreApplication::Resuming += ref new EventHandler<Object^>(this, &App::OnResuming);
+
+
+ DisplayProperties::LogicalDpiChanged +=
+ ref new DisplayPropertiesEventHandler(this, &App::OnLogicalDpiChanged);
+
+ CoreWindow^ window = Window::Current->CoreWindow;
+ window->SizeChanged +=
+ ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
+
+ window->PointerPressed +=
+ ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerPressed);
+
+ window->PointerReleased +=
+ ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerReleased);
+
+ window->PointerMoved +=
+ ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerMoved);
+
+
+ timer_ = ref new BasicTimer();
+
}
/// <summary>
{
//TODO: Save application state and stop any background activity
}
+
+//----------------------------------------------------------------------
+void App::OnRendering(
+ _In_ Object^ sender,
+ _In_ Object^ args
+ )
+{
+ timer_->Update();
+ simpleSprites_->Update(timer_->Total,timer_->Delta);
+ simpleSprites_->Render();
+ simpleSprites_->Present();
+
+}
+//--------------------------------------------------------------------------------------
+void App::OnWindowSizeChanged(
+ _In_ CoreWindow^ sender,
+ _In_ WindowSizeChangedEventArgs^ args
+ )
+{
+ simpleSprites_->UpdateForWindowSizeChange();
+
+}
+//--------------------------------------------------------------------------------------
+void App::OnLogicalDpiChanged(
+ _In_ Object^ sender
+ )
+{
+ simpleSprites_->SetDpi(DisplayProperties::LogicalDpi);
+}
+//--------------------------------------------------------------------------------------
+void App::OnWindowActivationChanged(
+ _In_ Platform::Object^ sender,
+ _In_ Windows::UI::Core::WindowActivatedEventArgs^ args
+ )
+{
+}
+//--------------------------------------------------------------------------------------
+void App::OnResuming(
+ _In_ Platform::Object^ sender,
+ _In_ Platform::Object^ args
+ )
+{
+}
+//--------------------------------------------------------------------------------------
+void App::OnViewStateChanged(
+ _In_ ApplicationView^ view,
+ _In_ ApplicationViewStateChangedEventArgs^ args
+ )
+{
+}
+
+void App::OnPointerPressed(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ )
+{
+ simpleSprites_->AddRepulsor(
+ args->CurrentPoint->PointerId,
+ float2(
+ args->CurrentPoint->Position.X,
+ args->CurrentPoint->Position.Y
+ )
+ );
+}
+
+void App::OnPointerReleased(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ )
+{
+ simpleSprites_->RemoveRepulsor(args->CurrentPoint->PointerId);
+}
+
+void App::OnPointerMoved(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ )
+{
+ if (args->CurrentPoint->IsInContact)
+ {
+ simpleSprites_->MoveRepulsor(
+ args->CurrentPoint->PointerId,
+ float2(
+ args->CurrentPoint->Position.X,
+ args->CurrentPoint->Position.Y
+ )
+ );
+ }
+}
+
#include "pch.h"
#include "App.g.h"
+#include "SimpleSprites.h"
+#include "BasicTimer.h"
namespace ShootingGame
{
private:
void OnSuspending(Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
+ SimpleSprites^ simpleSprites_;
+ BasicTimer^ timer_;
+ Windows::Foundation::EventRegistrationToken eventToken_;
+ void OnResuming(
+ _In_ Platform::Object^ sender,
+ _In_ Platform::Object^ args
+ );
+
+ void OnViewStateChanged(
+ _In_ Windows::UI::ViewManagement::ApplicationView^ view,
+ _In_ Windows::UI::ViewManagement::ApplicationViewStateChangedEventArgs^ args
+ );
+
+ void OnWindowActivationChanged(
+ _In_ Platform::Object^ sender,
+ _In_ Windows::UI::Core::WindowActivatedEventArgs^ args
+ );
+
+ void OnWindowSizeChanged(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::WindowSizeChangedEventArgs^ args
+ );
+
+ void OnLogicalDpiChanged(
+ _In_ Platform::Object^ sender
+ );
+
+ void OnRendering(
+ _In_ Object^ sender,
+ _In_ Object^ args
+ );
+ void OnPointerPressed(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ );
+
+ void OnPointerReleased(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ );
+ void OnPointerMoved(
+ _In_ Windows::UI::Core::CoreWindow^ sender,
+ _In_ Windows::UI::Core::PointerEventArgs^ args
+ );
+
+
+
};
}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+// This class provides a lightweight throttle feedback mechanism for
+// variable frame workloads. The class is initialized with a target
+// frame time and a "history" represented as bits in an unsigned int.
+// A 1 bit represents a frame that missed its target frame time.
+// If the past N frames, corresponding to the maskDecrease/maskIncrease
+// values, have all been missed or made, then the update method will
+// return a control recommendation to Decrease or Increase the frame
+// workload, respectively. The initial value for the frame history
+// is chosen such that the returned control recommendation is to maintain
+// frame workload until the history is primed with accurate values.
+
+#include "pch.h"
+#include "AutoThrottle.h"
+
+AutoThrottle::AutoThrottle(float targetFrameTime) :
+ m_missedFrameHistory(0xCCCCCCCC),
+ m_targetFrameTime(targetFrameTime)
+{
+}
+
+FrameWorkload AutoThrottle::Update(float frameTime)
+{
+ static const float epsilon = 0.005f; // Compensation for noise in the frameTime value.
+ static const unsigned int maskIncrease = 0x0000001F; // Require 5 made frames to increase workload.
+ static const unsigned int maskDecrease = 0x00000003; // Require 2 missed frames to decrease workload.
+
+ // Shift history back by one frame. The LSB represents the most recent frame.
+ m_missedFrameHistory <<= 1;
+
+ if (frameTime > m_targetFrameTime - epsilon)
+ {
+ m_missedFrameHistory |= 1;
+ }
+
+ if ((m_missedFrameHistory & maskIncrease) == 0)
+ {
+ return FrameWorkload::Increase;
+ }
+ if ((m_missedFrameHistory & maskDecrease) == maskDecrease)
+ {
+ return FrameWorkload::Decrease;
+ }
+
+ return FrameWorkload::Maintain;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+enum class FrameWorkload
+{
+ Increase,
+ Decrease,
+ Maintain
+};
+
+ref class AutoThrottle
+{
+public:
+ AutoThrottle(float targetFrameTime);
+ FrameWorkload Update(float frameTime);
+
+private:
+ unsigned int m_missedFrameHistory;
+ float m_targetFrameTime;
+};
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "BasicLoader.h"
+#include "BasicShapes.h"
+#include "DDSTextureLoader.h"
+#include "DirectXSample.h"
+#include <memory>
+
+using namespace Microsoft::WRL;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Foundation;
+using namespace Windows::ApplicationModel;
+
+BasicLoader::BasicLoader(
+ _In_ ID3D11Device* d3dDevice,
+ _In_opt_ IWICImagingFactory2* wicFactory
+ ) :
+ m_d3dDevice(d3dDevice),
+ m_wicFactory(wicFactory)
+{
+ // Create a new BasicReaderWriter to do raw file I/O.
+ m_basicReaderWriter = ref new BasicReaderWriter();
+}
+
+template<class DeviceChildType>
+inline void BasicLoader::SetDebugName(
+ _In_ DeviceChildType* object,
+ _In_ Platform::String^ name
+ )
+{
+#if defined(_DEBUG)
+ // Only assign debug names in debug builds.
+
+ char nameString[1024];
+ int nameStringLength = WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ name->Data(),
+ -1,
+ nameString,
+ 1024,
+ nullptr,
+ nullptr
+ );
+
+ if (nameStringLength == 0 )
+ {
+ char defaultNameString[] = "BasicLoaderObject";
+ DX::ThrowIfFailed(
+ object->SetPrivateData(
+ WKPDID_D3DDebugObjectName,
+ sizeof(defaultNameString) - 1,
+ defaultNameString
+ )
+ );
+ }
+ else
+ {
+ DX::ThrowIfFailed(
+ object->SetPrivateData(
+ WKPDID_D3DDebugObjectName,
+ nameStringLength - 1,
+ nameString
+ )
+ );
+ }
+#endif
+}
+
+Platform::String^ BasicLoader::GetExtension(
+ _In_ Platform::String^ filename
+ )
+{
+ int lastDotIndex = -1;
+ for (int i = filename->Length() - 1; i >= 0 && lastDotIndex == -1; i--)
+ {
+ if (*(filename->Data() + i) == '.')
+ {
+ lastDotIndex = i;
+ }
+ }
+ if (lastDotIndex != -1)
+ {
+ std::unique_ptr<wchar_t[]> extension(new wchar_t[filename->Length() - lastDotIndex]);
+ for (unsigned int i = 0; i < filename->Length() - lastDotIndex; i++)
+ {
+ extension[i] = tolower(*(filename->Data() + lastDotIndex + 1 + i));
+ }
+ return ref new Platform::String(extension.get());
+ }
+ return "";
+}
+
+void BasicLoader::CreateTexture(
+ _In_ bool decodeAsDDS,
+ _In_reads_bytes_(dataSize) byte* data,
+ _In_ uint32 dataSize,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_opt_ Platform::String^ debugName
+ )
+{
+ ComPtr<ID3D11ShaderResourceView> shaderResourceView;
+ ComPtr<ID3D11Texture2D> texture2D;
+
+ if (decodeAsDDS)
+ {
+ ComPtr<ID3D11Resource> resource;
+
+ if (textureView == nullptr)
+ {
+ CreateDDSTextureFromMemory(
+ m_d3dDevice.Get(),
+ data,
+ dataSize,
+ &resource,
+ nullptr
+ );
+ }
+ else
+ {
+ CreateDDSTextureFromMemory(
+ m_d3dDevice.Get(),
+ data,
+ dataSize,
+ &resource,
+ &shaderResourceView
+ );
+ }
+
+ DX::ThrowIfFailed(
+ resource.As(&texture2D)
+ );
+ }
+ else
+ {
+ if (m_wicFactory.Get() == nullptr)
+ {
+ // A WIC factory object is required in order to load texture
+ // assets stored in non-DDS formats. If BasicLoader was not
+ // initialized with one, create one as needed.
+ DX::ThrowIfFailed(
+ CoCreateInstance(
+ CLSID_WICImagingFactory,
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&m_wicFactory)
+ )
+ );
+ }
+
+ ComPtr<IWICStream> stream;
+ DX::ThrowIfFailed(
+ m_wicFactory->CreateStream(&stream)
+ );
+
+ DX::ThrowIfFailed(
+ stream->InitializeFromMemory(
+ data,
+ dataSize
+ )
+ );
+
+ ComPtr<IWICBitmapDecoder> bitmapDecoder;
+ DX::ThrowIfFailed(
+ m_wicFactory->CreateDecoderFromStream(
+ stream.Get(),
+ nullptr,
+ WICDecodeMetadataCacheOnDemand,
+ &bitmapDecoder
+ )
+ );
+
+ ComPtr<IWICBitmapFrameDecode> bitmapFrame;
+ DX::ThrowIfFailed(
+ bitmapDecoder->GetFrame(0, &bitmapFrame)
+ );
+
+ ComPtr<IWICFormatConverter> formatConverter;
+ DX::ThrowIfFailed(
+ m_wicFactory->CreateFormatConverter(&formatConverter)
+ );
+
+ DX::ThrowIfFailed(
+ formatConverter->Initialize(
+ bitmapFrame.Get(),
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.0,
+ WICBitmapPaletteTypeCustom
+ )
+ );
+
+ uint32 width;
+ uint32 height;
+ DX::ThrowIfFailed(
+ bitmapFrame->GetSize(&width, &height)
+ );
+
+ std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
+ DX::ThrowIfFailed(
+ formatConverter->CopyPixels(
+ nullptr,
+ width * 4,
+ width * height * 4,
+ bitmapPixels.get()
+ )
+ );
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ ZeroMemory(&initialData, sizeof(initialData));
+ initialData.pSysMem = bitmapPixels.get();
+ initialData.SysMemPitch = width * 4;
+ initialData.SysMemSlicePitch = 0;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateTexture2D(
+ &CD3D11_TEXTURE2D_DESC(
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ width,
+ height,
+ 1,
+ 1
+ ),
+ &initialData,
+ &texture2D
+ )
+ );
+
+ if (textureView != nullptr)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateShaderResourceView(
+ texture2D.Get(),
+ &CD3D11_SHADER_RESOURCE_VIEW_DESC(
+ texture2D.Get(),
+ D3D11_SRV_DIMENSION_TEXTURE2D
+ ),
+ &shaderResourceView
+ )
+ );
+ }
+ }
+
+ SetDebugName(texture2D.Get(), debugName);
+
+ if (texture != nullptr)
+ {
+ *texture = texture2D.Detach();
+ }
+ if (textureView != nullptr)
+ {
+ *textureView = shaderResourceView.Detach();
+ }
+}
+
+void BasicLoader::CreateInputLayout(
+ _In_reads_bytes_(bytecodeSize) byte* bytecode,
+ _In_ uint32 bytecodeSize,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC* layoutDesc,
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11InputLayout** layout
+ )
+{
+ if (layoutDesc == nullptr)
+ {
+ // If no input layout is specified, use the BasicVertex layout.
+ const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateInputLayout(
+ basicVertexLayoutDesc,
+ ARRAYSIZE(basicVertexLayoutDesc),
+ bytecode,
+ bytecodeSize,
+ layout
+ )
+ );
+ }
+ else
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateInputLayout(
+ layoutDesc,
+ layoutDescNumElements,
+ bytecode,
+ bytecodeSize,
+ layout
+ )
+ );
+ }
+}
+
+void BasicLoader::CreateMesh(
+ _In_ byte* meshData,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount,
+ _In_opt_ Platform::String^ debugName
+ )
+{
+ // The first 4 bytes of the BasicMesh format define the number of vertices in the mesh.
+ uint32 numVertices = *reinterpret_cast<uint32*>(meshData);
+
+ // The following 4 bytes define the number of indices in the mesh.
+ uint32 numIndices = *reinterpret_cast<uint32*>(meshData + sizeof(uint32));
+
+ // The next segment of the BasicMesh format contains the vertices of the mesh.
+ BasicVertex* vertices = reinterpret_cast<BasicVertex*>(meshData + sizeof(uint32) * 2);
+
+ // The last segment of the BasicMesh format contains the indices of the mesh.
+ uint16* indices = reinterpret_cast<uint16*>(meshData + sizeof(uint32) * 2 + sizeof(BasicVertex) * numVertices);
+
+ // Create the vertex and index buffers with the mesh data.
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
+ vertexBufferData.pSysMem = vertices;
+ vertexBufferData.SysMemPitch = 0;
+ vertexBufferData.SysMemSlicePitch = 0;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(numVertices * sizeof(BasicVertex), D3D11_BIND_VERTEX_BUFFER),
+ &vertexBufferData,
+ vertexBuffer
+ )
+ );
+
+ D3D11_SUBRESOURCE_DATA indexBufferData = {0};
+ indexBufferData.pSysMem = indices;
+ indexBufferData.SysMemPitch = 0;
+ indexBufferData.SysMemSlicePitch = 0;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(numIndices * sizeof(uint16), D3D11_BIND_INDEX_BUFFER),
+ &indexBufferData,
+ indexBuffer
+ )
+ );
+
+ SetDebugName(*vertexBuffer, Platform::String::Concat(debugName, "_VertexBuffer"));
+ SetDebugName(*indexBuffer, Platform::String::Concat(debugName, "_IndexBuffer"));
+
+ if (vertexCount != nullptr)
+ {
+ *vertexCount = numVertices;
+ }
+ if (indexCount != nullptr)
+ {
+ *indexCount = numIndices;
+ }
+}
+
+void BasicLoader::LoadTexture(
+ _In_ Platform::String^ filename,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView
+ )
+{
+ Platform::Array<byte>^ textureData = m_basicReaderWriter->ReadData(filename);
+
+ CreateTexture(
+ GetExtension(filename) == "dds",
+ textureData->Data,
+ textureData->Length,
+ texture,
+ textureView,
+ filename
+ );
+}
+
+void BasicLoader::LoadTextureAsync(
+ _In_ Platform::String^ filename,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ textureData, AsyncStatus /*status*/)
+ {
+ CreateTexture(
+ GetExtension(filename) == "dds",
+ textureData->Data,
+ textureData->Length,
+ texture,
+ textureView,
+ filename
+ );
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11VertexShader** shader,
+ _Out_opt_ ID3D11InputLayout** layout
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateVertexShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+
+ if (layout != nullptr)
+ {
+ CreateInputLayout(
+ bytecode->Data,
+ bytecode->Length,
+ layoutDesc,
+ layoutDescNumElements,
+ layout
+ );
+
+ SetDebugName(*layout, filename);
+ }
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11VertexShader** shader,
+ _Out_opt_ ID3D11InputLayout** layout
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateVertexShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+
+ if (layout != nullptr)
+ {
+ CreateInputLayout(
+ bytecode->Data,
+ bytecode->Length,
+ layoutDesc,
+ layoutDescNumElements,
+ layout
+ );
+
+ SetDebugName(*layout, filename);
+ }
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreatePixelShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreatePixelShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateComputeShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateComputeShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
+ _In_ uint32 numEntries,
+ _In_reads_opt_(numStrides) const uint32* bufferStrides,
+ _In_ uint32 numStrides,
+ _In_ uint32 rasterizedStream,
+ _Out_ ID3D11GeometryShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShaderWithStreamOutput(
+ bytecode->Data,
+ bytecode->Length,
+ streamOutDeclaration,
+ numEntries,
+ bufferStrides,
+ numStrides,
+ rasterizedStream,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
+ _In_ uint32 numEntries,
+ _In_reads_opt_(numStrides) const uint32* bufferStrides,
+ _In_ uint32 numStrides,
+ _In_ uint32 rasterizedStream,
+ _Out_ ID3D11GeometryShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShaderWithStreamOutput(
+ bytecode->Data,
+ bytecode->Length,
+ streamOutDeclaration,
+ numEntries,
+ bufferStrides,
+ numStrides,
+ rasterizedStream,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateHullShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateHullShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ )
+{
+ Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDomainShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+void BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDomainShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ }));
+}
+
+void BasicLoader::LoadMesh(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ )
+{
+ Platform::Array<byte>^ meshData = m_basicReaderWriter->ReadData(filename);
+
+ CreateMesh(
+ meshData->Data,
+ vertexBuffer,
+ indexBuffer,
+ vertexCount,
+ indexCount,
+ filename
+ );
+}
+
+void BasicLoader::LoadMeshAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ )
+{
+ m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ meshData, AsyncStatus /*status*/)
+ {
+ CreateMesh(
+ meshData->Data,
+ vertexBuffer,
+ indexBuffer,
+ vertexCount,
+ indexCount,
+ filename
+ );
+ }));
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "BasicReaderWriter.h"
+
+ref class BasicLoader
+{
+public:
+ BasicLoader(
+ _In_ ID3D11Device* d3dDevice,
+ _In_opt_ IWICImagingFactory2* wicFactory = nullptr
+ );
+
+ void LoadTexture(
+ _In_ Platform::String^ filename,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView
+ );
+
+ void LoadTextureAsync(
+ _In_ Platform::String^ filename,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11VertexShader** shader,
+ _Out_opt_ ID3D11InputLayout** layout
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11VertexShader** shader,
+ _Out_opt_ ID3D11InputLayout** layout
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
+ _In_ uint32 numEntries,
+ _In_reads_opt_(numStrides) const uint32* bufferStrides,
+ _In_ uint32 numStrides,
+ _In_ uint32 rasterizedStream,
+ _Out_ ID3D11GeometryShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
+ _In_ uint32 numEntries,
+ _In_reads_opt_(numStrides) const uint32* bufferStrides,
+ _In_ uint32 numStrides,
+ _In_ uint32 rasterizedStream,
+ _Out_ ID3D11GeometryShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ );
+
+ void LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ );
+
+ void LoadMesh(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ );
+
+ void LoadMeshAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ );
+
+private:
+ Microsoft::WRL::ComPtr<ID3D11Device> m_d3dDevice;
+ Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
+ BasicReaderWriter^ m_basicReaderWriter;
+
+ template<class DeviceChildType>
+ inline void SetDebugName(
+ _In_ DeviceChildType* object,
+ _In_ Platform::String^ name
+ );
+
+ Platform::String^ GetExtension(
+ _In_ Platform::String^ filename
+ );
+
+ void CreateTexture(
+ _In_ bool decodeAsDDS,
+ _In_reads_bytes_(dataSize) byte* data,
+ _In_ uint32 dataSize,
+ _Out_opt_ ID3D11Texture2D** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_opt_ Platform::String^ debugName
+ );
+
+ void CreateInputLayout(
+ _In_reads_bytes_(bytecodeSize) byte* bytecode,
+ _In_ uint32 bytecodeSize,
+ _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC* layoutDesc,
+ _In_ uint32 layoutDescNumElements,
+ _Out_ ID3D11InputLayout** layout
+ );
+
+ void CreateMesh(
+ _In_ byte* meshData,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount,
+ _In_opt_ Platform::String^ debugName
+ );
+};
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+// Template Vector & Matrix Classes
+
+template <class T> struct Vector2
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ };
+ struct
+ {
+ T r;
+ T g;
+ };
+ struct
+ {
+ T u;
+ T v;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { }
+};
+
+template <class T> struct Vector3
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ T z;
+ };
+ struct
+ {
+ T r;
+ T g;
+ T b;
+ };
+ struct
+ {
+ T u;
+ T v;
+ T w;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { }
+};
+
+template <class T> struct Vector4
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ T z;
+ T w;
+ };
+ struct
+ {
+ T r;
+ T g;
+ T b;
+ T a;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { }
+};
+
+template <class T> struct Matrix4x4
+{
+ union
+ {
+ struct
+ {
+ T _11; T _12; T _13; T _14;
+ T _21; T _22; T _23; T _24;
+ T _31; T _32; T _33; T _34;
+ T _41; T _42; T _43; T _44;
+ };
+ struct
+ {
+ T _m00; T _m01; T _m02; T _m03;
+ T _m10; T _m11; T _m12; T _m13;
+ T _m20; T _m21; T _m22; T _m23;
+ T _m30; T _m31; T _m32; T _m33;
+ };
+ };
+
+ Matrix4x4(T value = 0)
+ {
+ _11 = _12 = _13 = _14 = value;
+ _21 = _22 = _23 = _24 = value;
+ _31 = _32 = _33 = _34 = value;
+ _41 = _42 = _43 = _44 = value;
+ }
+
+ Matrix4x4(
+ T i11, T i12, T i13, T i14,
+ T i21, T i22, T i23, T i24,
+ T i31, T i32, T i33, T i34,
+ T i41, T i42, T i43, T i44
+ )
+ {
+ _11 = i11; _12 = i12; _13 = i13; _14 = i14;
+ _21 = i21; _22 = i22; _23 = i23; _24 = i24;
+ _31 = i31; _32 = i32; _33 = i33; _34 = i34;
+ _41 = i41; _42 = i42; _43 = i43; _44 = i44;
+ }
+
+ T* operator[](unsigned int index)
+ {
+ return &(reinterpret_cast<T*>(this)[index*4]);
+ }
+};
+
+// Template Vector Operations
+
+template <class T>
+T dot(Vector2<T> a, Vector2<T> b)
+{
+ return a.x * b.x + a.y * b.y;
+}
+
+template <class T>
+T dot(Vector3<T> a, Vector3<T> b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+template <class T>
+T dot(Vector4<T> a, Vector4<T> b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z + a.w + b.w;
+}
+
+template <class T>
+T length(Vector2<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y);
+}
+
+template <class T>
+T length(Vector3<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
+}
+
+template <class T>
+T length(Vector4<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w);
+}
+
+template <class T>
+Vector3<T> cross(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x));
+}
+
+template <class T>
+Vector2<T> normalize(Vector2<T> a)
+{
+ T len = length(a);
+ return Vector2<T>(a.x / len, a.y / len);
+}
+
+template <class T>
+Vector3<T> normalize(Vector3<T> a)
+{
+ T len = length(a);
+ return Vector3<T>(a.x / len, a.y / len, a.z / len);
+}
+
+template <class T>
+Vector4<T> normalize(Vector4<T> a)
+{
+ T len = length(a);
+ return Vector4<T>(a.x / len, a.y / len, a.z / len, a.w / len);
+}
+
+// Template Vector Operators
+
+template <class T>
+Vector2<T> operator-(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x - b.x, a.y - b.y);
+}
+
+template <class T>
+Vector2<T> operator-(Vector2<T> a)
+{
+ return Vector2<T>( -a.x, -a.y);
+}
+
+template <class T>
+Vector3<T> operator-(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+template <class T>
+Vector3<T> operator-(Vector3<T> a )
+{
+ return Vector3<T>( -a.x, -a.y, -a.z);
+}
+
+template <class T>
+Vector4<T> operator-(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
+
+template <class T>
+Vector4<T> operator-(Vector4<T> a )
+{
+ return Vector4<T>( -a.x, -a.y, -a.z, -a.w);
+}
+
+template <class T>
+Vector2<T> operator+(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x + b.x, a.y + b.y);
+}
+
+template <class T>
+Vector3<T> operator+(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+template <class T>
+Vector4<T> operator+(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
+
+template <class T>
+Vector2<T> operator*(Vector2<T> a, T s)
+{
+ return Vector2<T>(a.x * s, a.y * s);
+}
+
+template <class T>
+Vector2<T> operator*(T s, Vector2<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector2<T> operator*(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x * b.x, a.y * b.y);
+}
+
+template <class T>
+Vector2<T> operator/(Vector2<T> a, T s)
+{
+ return Vector2<T>(a.x / s, a.y / s);
+}
+
+template <class T>
+Vector3<T> operator*(Vector3<T> a, T s)
+{
+ return Vector3<T>(a.x * s, a.y * s, a.z * s);
+}
+
+template <class T>
+Vector3<T> operator*(T s, Vector3<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector3<T> operator*(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x * b.x, a.y * b.y, a.z * b.z);
+}
+
+template <class T>
+Vector3<T> operator/(Vector3<T> a, T s)
+{
+ return Vector3<T>(a.x / s, a.y / s, a.z / s);
+}
+
+template <class T>
+Vector4<T> operator*(Vector4<T> a, T s)
+{
+ return Vector4<T>(a.x * s, a.y * s, a.z * s, a.w * s);
+}
+
+template <class T>
+Vector4<T> operator*(T s, Vector4<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector4<T> operator*(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+}
+
+template <class T>
+Vector4<T> operator/(Vector4<T> a, T s)
+{
+ return Vector4<T>(a.x / s, a.y / s, a.z / s, a.w / s);
+}
+
+
+
+// Template Matrix Operations
+
+template <class T>
+Matrix4x4<T> transpose(Matrix4x4<T> m)
+{
+ return Matrix4x4<T>(
+ m._11, m._21, m._31, m._41,
+ m_.12, m._22, m._32, m._42,
+ m._13, m._23, m._33, m._43,
+ m._14, m._24, m._34, m._44
+ );
+}
+
+template <class T>
+Matrix4x4<T> mul(Matrix4x4<T> m1, Matrix4x4<T> m2)
+{
+ Matrix4x4<T> mOut;
+
+ for(int i=0;i<4;i++)
+ {
+ for(int j=0;j<4;j++)
+ {
+ for(int k=0;k<4;k++)
+ {
+ mOut[i][j] += m1[i][k] * m2[k][j];
+ }
+ }
+ }
+
+ return mOut;
+}
+
+// Common HLSL-compatible vector typedefs
+
+typedef unsigned int uint;
+
+typedef Vector2<float> float2;
+typedef Vector3<float> float3;
+typedef Vector4<float> float4;
+
+typedef Matrix4x4<float> float4x4;
+
+// Standard Matrix Intializers
+
+inline float4x4 identity()
+{
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 translation(float x, float y, float z)
+{
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = x;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = y;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = z;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 scale(float x, float y, float z)
+{
+ float4x4 mOut;
+
+ mOut._11 = x; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = y; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = z; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationX(float degreeX)
+{
+ float angleInRadians = degreeX * ((float)M_PI / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationY(float degreeY)
+{
+ float angleInRadians = degreeY * ((float)M_PI / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationZ(float degreeZ)
+{
+ float angleInRadians = degreeZ * ((float)M_PI / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+// 3D Rotation matrix for an arbitrary axis specified by x, y and z
+inline float4x4 rotationArbitrary(float3 axis, float degree)
+{
+ axis = normalize(axis);
+
+ float angleInRadians = degree * ((float)M_PI / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+ float oneMinusCosAngle = 1 - cosAngle;
+
+ float4x4 mOut;
+
+ mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f);
+ mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y;
+ mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z;
+ mOut._41 = 0.0f;
+
+ mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x;
+ mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f);
+ mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z;
+ mOut._24 = 0.0f;
+
+ mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x;
+ mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y;
+ mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f);
+ mOut._34 = 0.0f;
+
+ mOut._41 = 0.0f;
+ mOut._42 = 0.0f;
+ mOut._43 = 0.0f;
+ mOut._44 = 1.0f;
+
+ return mOut;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "BasicReaderWriter.h"
+#include <ppltasks.h>
+
+using namespace Microsoft::WRL;
+using namespace Windows::Storage;
+using namespace Windows::Storage::FileProperties;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Foundation;
+using namespace Windows::ApplicationModel;
+using namespace Concurrency;
+
+BasicReaderWriter::BasicReaderWriter()
+{
+ m_location = Package::Current->InstalledLocation;
+ m_locationPath = Platform::String::Concat(m_location->Path, "\\");
+}
+
+BasicReaderWriter::BasicReaderWriter(
+ _In_ Windows::Storage::StorageFolder^ folder
+ )
+{
+ m_location = folder;
+ Platform::String^ path = m_location->Path;
+ if (path->Length() == 0)
+ {
+ // Applications are not permitted to access certain
+ // folders, such as the Documents folder, using this
+ // code path. In such cases, the Path property for
+ // the folder will be an empty string.
+ throw ref new Platform::FailureException();
+ }
+ m_locationPath = Platform::String::Concat(path, "\\");
+}
+
+Platform::Array<byte>^ BasicReaderWriter::ReadData(
+ _In_ Platform::String^ filename
+ )
+{
+ CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
+ extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+ extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
+ extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ extendedParams.lpSecurityAttributes = nullptr;
+ extendedParams.hTemplateFile = nullptr;
+
+ Wrappers::FileHandle file(
+ CreateFile2(
+ Platform::String::Concat(m_locationPath, filename)->Data(),
+ GENERIC_READ,
+ 0,
+ OPEN_EXISTING,
+ &extendedParams
+ )
+ );
+ if (file.Get()==INVALID_HANDLE_VALUE)
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ FILE_STANDARD_INFO fileInfo = {0};
+ if (!GetFileInformationByHandleEx(
+ file.Get(),
+ FileStandardInfo,
+ &fileInfo,
+ sizeof(fileInfo)
+ ))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ if (fileInfo.EndOfFile.HighPart != 0)
+ {
+ throw ref new Platform::OutOfMemoryException();
+ }
+
+ Platform::Array<byte>^ fileData = ref new Platform::Array<byte>(fileInfo.EndOfFile.LowPart);
+
+ if (!ReadFile(
+ file.Get(),
+ fileData->Data,
+ fileData->Length,
+ nullptr,
+ nullptr
+ ) )
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ return fileData;
+}
+
+void BasicReaderWriter::ReadDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ ReadDataAsyncCallback^ callback
+ )
+{
+ task<StorageFile^>(m_location->GetFileAsync(filename)).then([=](StorageFile^ file)
+ {
+ return FileIO::ReadBufferAsync(file);
+ }).then([=](IBuffer^ buffer)
+ {
+ auto fileData = ref new Platform::Array<byte>(buffer->Length);
+ DataReader::FromBuffer(buffer)->ReadBytes(fileData);
+ callback(fileData, AsyncStatus::Completed);
+ });
+}
+
+uint32 BasicReaderWriter::WriteData(
+ _In_ Platform::String^ filename,
+ _In_ Platform::Array<byte>^ fileData
+ )
+{
+ CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
+ extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+ extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
+ extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ extendedParams.lpSecurityAttributes = nullptr;
+ extendedParams.hTemplateFile = nullptr;
+
+ Wrappers::FileHandle file(
+ CreateFile2(
+ Platform::String::Concat(m_locationPath, filename)->Data(),
+ GENERIC_WRITE,
+ 0,
+ CREATE_ALWAYS,
+ &extendedParams
+ )
+ );
+ if (file.Get()==INVALID_HANDLE_VALUE)
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ DWORD numBytesWritten;
+ if (
+ !WriteFile(
+ file.Get(),
+ fileData->Data,
+ fileData->Length,
+ &numBytesWritten,
+ nullptr
+ ) ||
+ numBytesWritten != fileData->Length
+ )
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ return numBytesWritten;
+}
+
+void BasicReaderWriter::WriteDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ Platform::Array<byte>^ fileData,
+ _In_ WriteDataAsyncCallback^ callback
+ )
+{
+ task<StorageFile^>(m_location->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([=](StorageFile^ file)
+ {
+ return FileIO::WriteBytesAsync(file, fileData);
+ }).then([=]()
+ {
+ callback(AsyncStatus::Completed);
+ });
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+// Define the arguments for the async callbacks.
+delegate void ReadDataAsyncCallback(Platform::Array<byte>^, Windows::Foundation::AsyncStatus);
+delegate void WriteDataAsyncCallback(Windows::Foundation::AsyncStatus);
+
+ref class BasicReaderWriter
+{
+private:
+ Windows::Storage::StorageFolder^ m_location;
+ Platform::String^ m_locationPath;
+
+public:
+ BasicReaderWriter();
+ BasicReaderWriter(
+ _In_ Windows::Storage::StorageFolder^ folder
+ );
+
+ Platform::Array<byte>^ ReadData(
+ _In_ Platform::String^ filename
+ );
+
+ void ReadDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ ReadDataAsyncCallback^ callback
+ );
+
+ uint32 WriteData(
+ _In_ Platform::String^ filename,
+ _In_ Platform::Array<byte>^ fileData
+ );
+
+ void WriteDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ Platform::Array<byte>^ fileData,
+ _In_ WriteDataAsyncCallback^ callback
+ );
+};
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "BasicMath.h"
+
+// this struct represents the vertex format for the shapes generated in the functions below
+struct BasicVertex
+{
+ float3 pos; // position
+ float3 norm; // surface normal vector
+ float2 tex; // texture coordinate
+};
+
+// this struct represents the vertex format for all shapes generated in the functions below
+struct TangentVertex
+{
+ float3 pos; // position
+ float2 tex; // texture coordinate
+ float3 uTan; // texture coordinate u-tangent vector
+ float3 vTan; // texture coordinate v-tangent vector
+};
+
+ref class BasicShapes
+{
+public:
+ BasicShapes(ID3D11Device *d3dDevice);
+ void CreateCube(
+ _Out_ ID3D11Buffer **vertexBuffer,
+ _Out_ ID3D11Buffer **indexBuffer,
+ _Out_opt_ unsigned int *vertexCount,
+ _Out_opt_ unsigned int *indexCount
+ );
+ void CreateBox(
+ float3 radii,
+ _Out_ ID3D11Buffer **vertexBuffer,
+ _Out_ ID3D11Buffer **indexBuffer,
+ _Out_opt_ unsigned int *vertexCount,
+ _Out_opt_ unsigned int *indexCount
+ );
+ void CreateSphere(
+ _Out_ ID3D11Buffer **vertexBuffer,
+ _Out_ ID3D11Buffer **indexBuffer,
+ _Out_opt_ unsigned int *vertexCount,
+ _Out_opt_ unsigned int *indexCount
+ );
+ void CreateTangentSphere(
+ _Out_ ID3D11Buffer **vertexBuffer,
+ _Out_ ID3D11Buffer **indexBuffer,
+ _Out_opt_ unsigned int *vertexCount,
+ _Out_opt_ unsigned int *indexCount
+ );
+ void CreateReferenceAxis(
+ _Out_ ID3D11Buffer **vertexBuffer,
+ _Out_ ID3D11Buffer **indexBuffer,
+ _Out_opt_ unsigned int *vertexCount,
+ _Out_opt_ unsigned int *indexCount
+ );
+
+private:
+ Microsoft::WRL::ComPtr<ID3D11Device> m_d3dDevice;
+
+ void CreateVertexBuffer(
+ _In_ unsigned int numVertices,
+ _In_ BasicVertex *vertexData,
+ _Out_ ID3D11Buffer **vertexBuffer
+ );
+
+ void CreateIndexBuffer(
+ _In_ unsigned int numIndices,
+ _In_ unsigned short *indexData,
+ _Out_ ID3D11Buffer **indexBuffer
+ );
+
+ void CreateTangentVertexBuffer(
+ _In_ unsigned int numVertices,
+ _In_ TangentVertex *vertexData,
+ _Out_ ID3D11Buffer **vertexBuffer
+ );
+
+};
--- /dev/null
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//----------------------------------------------------------------------
+
+cbuffer RenderTargetInfoCB
+{
+ float2 renderTargetSize;
+};
+
+struct GeometryShaderInput
+{
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 color : COLOR0;
+};
+
+struct PixelShaderInput
+{
+ float4 pos : SV_POSITION;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+// This shader generates two triangles that will be used to draw the sprite.
+// The vertex properties are calculated based on the per-sprite instance data
+// passed in from the vertex shader.
+
+[maxvertexcount(4)]
+void main(point GeometryShaderInput input[1], inout TriangleStream<PixelShaderInput> spriteStream)
+{
+ float sinRotation;
+ float cosRotation;
+ sincos(input[0].rotation, sinRotation, cosRotation);
+
+ float2 texCoord[4];
+ texCoord[0] = float2(0,0);
+ texCoord[1] = float2(1,0);
+ texCoord[2] = float2(0,1);
+ texCoord[3] = float2(1,1);
+
+ float2 posDelta[4];
+ posDelta[0] = float2(-input[0].offset.x, input[0].offset.y);
+ posDelta[1] = float2( input[0].offset.x, input[0].offset.y);
+ posDelta[2] = float2(-input[0].offset.x, -input[0].offset.y);
+ posDelta[3] = float2( input[0].offset.x, -input[0].offset.y);
+
+ spriteStream.RestartStrip();
+ [unroll]
+ for (int i = 0; i < 4; i++)
+ {
+ posDelta[i] = float2(
+ posDelta[i].x * cosRotation - posDelta[i].y * sinRotation,
+ posDelta[i].x * sinRotation + posDelta[i].y * cosRotation
+ );
+ posDelta[i] /= renderTargetSize;
+ PixelShaderInput streamElement;
+ streamElement.pos = float4(input[0].origin + posDelta[i], 0.5f, 1.0f);
+ streamElement.tex = texCoord[i];
+ streamElement.color = input[0].color;
+ spriteStream.Append(streamElement);
+ }
+ spriteStream.RestartStrip();
+}
--- /dev/null
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//----------------------------------------------------------------------
+
+struct VertexShaderInput
+{
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 color : COLOR0;
+};
+
+struct GeometryShaderInput
+{
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 color : COLOR0;
+};
+
+// This shader simply passes per-sprite instance data to the geometry shader.
+
+GeometryShaderInput main(VertexShaderInput input)
+{
+ GeometryShaderInput ret;
+ ret.origin = input.origin;
+ ret.offset = input.offset;
+ ret.rotation = input.rotation;
+ ret.color = input.color;
+ return ret;
+}
--- /dev/null
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//----------------------------------------------------------------------
+
+cbuffer RenderTargetInfoCB
+{
+ float2 renderTargetSize;
+};
+
+struct VertexShaderInput
+{
+ float2 pos : POSITION;
+ float2 tex : TEXCOORD0;
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 color : COLOR0;
+};
+
+struct PixelShaderInput
+{
+ float4 pos : SV_POSITION;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+// This shader takes a fixed-position vertex buffer, and using per-sprite
+// instance data, transforms the vertices so that the sprite is rendered
+// at the desired position, rotation, and scale.
+
+PixelShaderInput main(VertexShaderInput input)
+{
+ PixelShaderInput ret;
+ float sinRotation;
+ float cosRotation;
+ sincos(input.rotation, sinRotation, cosRotation);
+ float2 posDelta = input.pos * input.offset;
+ posDelta = float2(
+ posDelta.x * cosRotation - posDelta.y * sinRotation,
+ posDelta.x * sinRotation + posDelta.y * cosRotation
+ );
+ posDelta /= renderTargetSize;
+ ret.pos = float4(input.origin + posDelta, 0.5f, 1.0f);
+ ret.tex = input.tex;
+ ret.color = input.color;
+ return ret;
+}
--- /dev/null
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//----------------------------------------------------------------------
+
+struct VertexShaderInput
+{
+ float2 pos : POSITIONT;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+struct PixelShaderInput
+{
+ float4 pos : SV_POSITION;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+// This shader simply passes pre-transformed vertex data to the pixel shader.
+
+PixelShaderInput main(VertexShaderInput input)
+{
+ PixelShaderInput ret;
+ ret.pos = float4(input.pos, 0.5f, 1.0f);
+ ret.tex = input.tex;
+ ret.color = input.color;
+ return ret;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "BasicSprites.h"
+#include "DirectXSample.h"
+#include "BasicLoader.h"
+
+// Display a performance warning message in Debug builds.
+#if defined(_DEBUG)
+#pragma message("Warning: SpriteBatch performance is significantly decreased in the Debug configuration. Switch to the Release configuration for better performance.")
+#endif
+
+using namespace Microsoft::WRL;
+using namespace BasicSprites;
+
+SpriteBatch::SpriteBatch() :
+ m_capacity(0)
+{
+}
+
+void SpriteBatch::Initialize(
+ _In_ ID3D11Device1* d3dDevice,
+ _In_ int capacity = 1024
+ )
+{
+ m_d3dDevice = d3dDevice;
+ m_d3dDevice->GetImmediateContext1(&m_d3dContext);
+ m_capacity = capacity;
+
+ // Determine the technique that will be used to render the sprites.
+ auto featureLevel = m_d3dDevice->GetFeatureLevel();
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_10_0)
+ {
+ // On DirectX 10+ devices, the Geometry Shader allows the sprite vertices to be
+ // generated on the GPU, significantly reducing memory bandwidth requirements.
+ m_technique = RenderTechnique::GeometryShader;
+ }
+ else if (featureLevel >= D3D_FEATURE_LEVEL_9_3)
+ {
+ // On DirectX 9.3+ devices, instancing allows shared sprite geometry with unique
+ // per-sprite instance parameters, eliminating redundant data transfer.
+ m_technique = RenderTechnique::Instancing;
+ }
+ else
+ {
+ // On devices that do not support Instancing, sprite vertex data must be replicated
+ // in order to achieve the desired effect.
+ m_technique = RenderTechnique::Replication;
+
+ if (capacity > static_cast<int>(Parameters::MaximumCapacityCompatible))
+ {
+ // The index buffer format for feature-level 9.1 devices may only be 16 bits.
+ // With 4 vertices per sprite, this allows a maximum of (1 << 16) / 4 sprites.
+ throw ref new Platform::InvalidArgumentException();
+ }
+ }
+
+ // Create the texture sampler.
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ ZeroMemory(&samplerDesc, sizeof(samplerDesc));
+ samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.MipLODBias = 0.0f;
+ samplerDesc.MaxAnisotropy = 0;
+ samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = 0.0f;
+ samplerDesc.MaxLOD = FLT_MAX;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateSamplerState(
+ &samplerDesc,
+ &m_linearSampler
+ )
+ );
+
+ // Create the blend states.
+
+ D3D11_BLEND_DESC1 blendDesc;
+ ZeroMemory(&blendDesc, sizeof(blendDesc));
+ blendDesc.AlphaToCoverageEnable = false;
+ blendDesc.IndependentBlendEnable = false;
+ blendDesc.RenderTarget[0].BlendEnable = true;
+ blendDesc.RenderTarget[0].LogicOpEnable = false;
+ blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+ blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
+ blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBlendState1(
+ &blendDesc,
+ &m_blendStateAlpha
+ )
+ );
+
+ blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBlendState1(
+ &blendDesc,
+ &m_blendStateAdditive
+ )
+ );
+
+ BasicLoader^ loader = ref new BasicLoader(m_d3dDevice.Get());
+
+ if (m_technique == RenderTechnique::GeometryShader)
+ {
+ D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
+ {
+ { "TRANSFORM", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 2, DXGI_FORMAT_R32_FLOAT, 0, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 20, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
+ };
+ loader->LoadShader(
+ "BasicSprites.GeometryShader.vs.cso",
+ layoutDesc,
+ ARRAYSIZE(layoutDesc),
+ &m_vertexShader,
+ &m_inputLayout
+ );
+ loader->LoadShader(
+ "BasicSprites.GeometryShader.gs.cso",
+ &m_geometryShader
+ );
+ }
+ else if (m_technique == RenderTechnique::Instancing)
+ {
+ D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TRANSFORM", 0, DXGI_FORMAT_R32G32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 1, DXGI_FORMAT_R32G32_FLOAT, 1, 8, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 2, DXGI_FORMAT_R32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 20, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
+ };
+ loader->LoadShader(
+ "BasicSprites.Instancing.vs.cso",
+ layoutDesc,
+ ARRAYSIZE(layoutDesc),
+ &m_vertexShader,
+ &m_inputLayout
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
+ {
+ { "POSITIONT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+ };
+ loader->LoadShader(
+ "BasicSprites.Replication.vs.cso",
+ layoutDesc,
+ ARRAYSIZE(layoutDesc),
+ &m_vertexShader,
+ &m_inputLayout
+ );
+ }
+
+ loader->LoadShader(
+ "BasicSprites.ps.cso",
+ &m_pixelShader
+ );
+
+ // Create buffers.
+
+ if (m_technique == RenderTechnique::GeometryShader)
+ {
+ // Create the instance data buffer.
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ m_capacity * sizeof(InstanceData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ nullptr,
+ &m_instanceDataBuffer
+ )
+ );
+
+ m_instanceData.reset(new InstanceData[m_capacity]);
+ }
+ else if (m_technique == RenderTechnique::Instancing)
+ {
+ // Create the vertex buffer.
+
+ InstancingVertex vertexBufferData[] =
+ {
+ { float2(-1.0f, 1.0f), float2(0.0f, 0.0f) },
+ { float2( 1.0f, 1.0f), float2(1.0f, 0.0f) },
+ { float2(-1.0f, -1.0f), float2(0.0f, 1.0f) },
+ { float2( 1.0f, -1.0f), float2(1.0f, 1.0f) }
+ };
+
+ D3D11_SUBRESOURCE_DATA vertexInitialData;
+ vertexInitialData.pSysMem = vertexBufferData;
+ vertexInitialData.SysMemPitch = 0;
+ vertexInitialData.SysMemSlicePitch = 0;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ sizeof(vertexBufferData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ &vertexInitialData,
+ &m_vertexBuffer
+ )
+ );
+
+ // Create the instance data buffer.
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ m_capacity * sizeof(InstanceData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ nullptr,
+ &m_instanceDataBuffer
+ )
+ );
+
+ m_instanceData.reset(new InstanceData[m_capacity]);
+
+ // Create the index buffer.
+
+ unsigned int indexBufferData[] =
+ {
+ 0, 1, 2,
+ 1, 3, 2
+ };
+
+ D3D11_SUBRESOURCE_DATA indexInitialData;
+ indexInitialData.pSysMem = indexBufferData;
+ indexInitialData.SysMemPitch = 0;
+ indexInitialData.SysMemSlicePitch = 0;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ sizeof(indexBufferData),
+ D3D11_BIND_INDEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ &indexInitialData,
+ &m_indexBuffer
+ )
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ // Create the vertex buffer.
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ m_capacity * 4 * sizeof(ReplicationVertex),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ nullptr,
+ &m_vertexBuffer
+ )
+ );
+
+ m_vertexData.reset(new ReplicationVertex[m_capacity * 4]);
+
+ // Create the index buffer.
+
+ std::unique_ptr<unsigned short[]> indexBufferData(new unsigned short[m_capacity * 6]);
+
+ for (int i = 0; i < m_capacity; i++)
+ {
+ indexBufferData[i * 6 + 0] = i * 4 + 0;
+ indexBufferData[i * 6 + 1] = i * 4 + 1;
+ indexBufferData[i * 6 + 2] = i * 4 + 2;
+ indexBufferData[i * 6 + 3] = i * 4 + 1;
+ indexBufferData[i * 6 + 4] = i * 4 + 3;
+ indexBufferData[i * 6 + 5] = i * 4 + 2;
+ }
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = indexBufferData.get();
+ initialData.SysMemPitch = 0;
+ initialData.SysMemSlicePitch = 0;
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ m_capacity * 6 * sizeof(unsigned short),
+ D3D11_BIND_INDEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ ),
+ &initialData,
+ &m_indexBuffer
+ )
+ );
+ }
+
+ if (m_technique == RenderTechnique::GeometryShader || m_technique == RenderTechnique::Instancing)
+ {
+ // Both the Geometry Shader and Instancing techniques scale geometry in shader code.
+ // As a result, they require information about the render target size.
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &CD3D11_BUFFER_DESC(
+ 16, // Constant buffer sizes must be a multiple of 16 bytes. 16 is sufficient for the required float2 data.
+ D3D11_BIND_CONSTANT_BUFFER,
+ D3D11_USAGE_DYNAMIC,
+ D3D11_CPU_ACCESS_WRITE
+ ),
+ nullptr,
+ &m_renderTargetInfoCbuffer
+ )
+ );
+ }
+}
+
+void SpriteBatch::AddTexture(
+ _In_ ID3D11Texture2D* texture
+ )
+{
+ TextureMapElement mapElement;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateShaderResourceView(
+ texture,
+ &CD3D11_SHADER_RESOURCE_VIEW_DESC(
+ texture,
+ D3D11_SRV_DIMENSION_TEXTURE2D
+ ),
+ &mapElement.srv
+ )
+ );
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture->GetDesc(&textureDesc);
+ mapElement.size = float2(
+ static_cast<float>(textureDesc.Width),
+ static_cast<float>(textureDesc.Height)
+ );
+
+ m_textureMap[texture] = mapElement;
+}
+
+void SpriteBatch::RemoveTexture(
+ _In_ ID3D11Texture2D* texture
+ )
+{
+ m_textureMap.erase(texture);
+}
+
+void SpriteBatch::Begin()
+{
+ // Reset internal sprite data.
+
+ m_numSpritesDrawn = 0;
+ m_spritesInRun = 0;
+ m_spriteRuns.clear();
+
+ // Get the current render target dimensions and logical DPI.
+
+ ComPtr<ID3D11RenderTargetView> renderTargetView;
+ m_d3dContext->OMGetRenderTargets(
+ 1,
+ &renderTargetView,
+ nullptr
+ );
+
+ ComPtr<ID3D11Resource> renderTarget;
+ renderTargetView->GetResource(&renderTarget);
+
+ ComPtr<ID3D11Texture2D> renderTargetTexture;
+ renderTarget.As(&renderTargetTexture);
+
+ D3D11_TEXTURE2D_DESC renderTargetTextureDesc;
+ renderTargetTexture->GetDesc(&renderTargetTextureDesc);
+
+ m_renderTargetSize = float2(
+ static_cast<float>(renderTargetTextureDesc.Width),
+ static_cast<float>(renderTargetTextureDesc.Height)
+ );
+
+ m_dpi = Windows::Graphics::Display::DisplayProperties::LogicalDpi;
+}
+
+void SpriteBatch::End()
+{
+ // If no sprites were drawn, do nothing.
+ if (m_numSpritesDrawn == 0)
+ {
+ return;
+ }
+
+ // Save the final sprite run info.
+
+ SpriteRunInfo runInfo;
+ runInfo.textureView = m_currentTextureView;
+ runInfo.blendState = m_currentBlendState;
+ runInfo.numSprites = m_spritesInRun;
+ m_spriteRuns.push_back(runInfo);
+
+ // Update the buffer data.
+
+ if (m_technique == RenderTechnique::GeometryShader || m_technique == RenderTechnique::Instancing)
+ {
+ m_d3dContext->UpdateSubresource(
+ m_instanceDataBuffer.Get(),
+ 0,
+ &CD3D11_BOX(0, 0, 0, sizeof(InstanceData) * m_numSpritesDrawn, 1, 1),
+ m_instanceData.get(),
+ 0,
+ 0
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ m_d3dContext->UpdateSubresource(
+ m_vertexBuffer.Get(),
+ 0,
+ &CD3D11_BOX(0, 0, 0, sizeof(ReplicationVertex) * m_numSpritesDrawn * 4, 1, 1),
+ m_vertexData.get(),
+ 0,
+ 0
+ );
+ }
+
+ if (m_technique == RenderTechnique::GeometryShader || m_technique == RenderTechnique::Instancing)
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedSubresource;
+ m_d3dContext->Map(
+ m_renderTargetInfoCbuffer.Get(),
+ 0,
+ D3D11_MAP_WRITE_DISCARD,
+ 0,
+ &mappedSubresource
+ );
+ *static_cast<float2*>(mappedSubresource.pData) = m_renderTargetSize;
+ m_d3dContext->Unmap(
+ m_renderTargetInfoCbuffer.Get(),
+ 0
+ );
+ }
+
+ // Set the pipeline state
+
+ if (m_technique == RenderTechnique::Instancing)
+ {
+ m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ m_d3dContext->IASetIndexBuffer(
+ m_indexBuffer.Get(),
+ DXGI_FORMAT_R32_UINT,
+ 0
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ m_d3dContext->IASetIndexBuffer(
+ m_indexBuffer.Get(),
+ DXGI_FORMAT_R16_UINT,
+ 0
+ );
+ }
+ else if (m_technique == RenderTechnique::GeometryShader)
+ {
+ m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+ m_d3dContext->GSSetShader(
+ m_geometryShader.Get(),
+ nullptr,
+ 0
+ );
+ }
+
+ m_d3dContext->IASetInputLayout(m_inputLayout.Get());
+
+ m_d3dContext->VSSetShader(
+ m_vertexShader.Get(),
+ nullptr,
+ 0
+ );
+
+ if (m_technique == RenderTechnique::GeometryShader)
+ {
+ m_d3dContext->GSSetConstantBuffers(
+ 0,
+ 1,
+ m_renderTargetInfoCbuffer.GetAddressOf()
+ );
+ }
+ else if (m_technique == RenderTechnique::Instancing)
+ {
+ m_d3dContext->VSSetConstantBuffers(
+ 0,
+ 1,
+ m_renderTargetInfoCbuffer.GetAddressOf()
+ );
+ }
+
+ m_d3dContext->PSSetShader(
+ m_pixelShader.Get(),
+ nullptr,
+ 0
+ );
+
+ m_d3dContext->PSSetSamplers(
+ 0,
+ 1,
+ m_linearSampler.GetAddressOf()
+ );
+
+ if (m_technique == RenderTechnique::GeometryShader)
+ {
+ unsigned int stride = sizeof(InstanceData);
+ unsigned int offset = 0;
+ m_d3dContext->IASetVertexBuffers(
+ 0,
+ 1,
+ m_instanceDataBuffer.GetAddressOf(),
+ &stride,
+ &offset
+ );
+ }
+ else if (m_technique == RenderTechnique::Instancing)
+ {
+ unsigned int stride = sizeof(InstancingVertex);
+ unsigned int offset = 0;
+ m_d3dContext->IASetVertexBuffers(
+ 0,
+ 1,
+ m_vertexBuffer.GetAddressOf(),
+ &stride,
+ &offset
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ unsigned int stride = sizeof(ReplicationVertex);
+ unsigned int offset = 0;
+ m_d3dContext->IASetVertexBuffers(
+ 0,
+ 1,
+ m_vertexBuffer.GetAddressOf(),
+ &stride,
+ &offset
+ );
+ }
+
+ // Draw each sprite run
+
+ unsigned int indexBase = 0;
+ for (auto runIterator = m_spriteRuns.begin(); runIterator != m_spriteRuns.end(); runIterator++)
+ {
+ m_d3dContext->PSSetShaderResources(
+ 0,
+ 1,
+ &runIterator->textureView
+ );
+
+ const FLOAT blendFactor[] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ m_d3dContext->OMSetBlendState(
+ runIterator->blendState,
+ nullptr,
+ 0xFFFFFFFF
+ );
+
+ if (m_technique == RenderTechnique::GeometryShader)
+ {
+ unsigned int instancesToDraw = runIterator->numSprites;
+ m_d3dContext->DrawInstanced(
+ 1,
+ instancesToDraw,
+ 0,
+ indexBase
+ );
+ indexBase += instancesToDraw;
+ }
+ else if (m_technique == RenderTechnique::Instancing)
+ {
+ unsigned int instancesToDraw = runIterator->numSprites;
+ unsigned int stride = sizeof(InstanceData);
+ unsigned int offset = indexBase * stride;
+ // Instance data offset must be zero for the draw call on feature level 9.3 and below.
+ // Instead, set the offset in the input assembler.
+ m_d3dContext->IASetVertexBuffers(
+ 1,
+ 1,
+ m_instanceDataBuffer.GetAddressOf(),
+ &stride,
+ &offset
+ );
+ m_d3dContext->DrawIndexedInstanced(
+ 6,
+ instancesToDraw,
+ 0,
+ 0,
+ 0
+ );
+ indexBase += instancesToDraw;
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ unsigned int indicesToDraw = runIterator->numSprites * 6;
+ m_d3dContext->DrawIndexed(indicesToDraw, indexBase, 0);
+ indexBase += indicesToDraw;
+ }
+ }
+}
+
+unsigned int SpriteBatch::MakeUnorm(float4 color)
+{
+ unsigned int r = max(0, min(255, static_cast<unsigned int>(color.r * 255.0f)));
+ unsigned int g = max(0, min(255, static_cast<unsigned int>(color.g * 255.0f)));
+ unsigned int b = max(0, min(255, static_cast<unsigned int>(color.b * 255.0f)));
+ unsigned int a = max(0, min(255, static_cast<unsigned int>(color.a * 255.0f)));
+ return
+ (a << 24) |
+ (b << 16) |
+ (g << 8) |
+ r;
+}
+
+float2 SpriteBatch::StandardOrigin(float2 position, PositionUnits positionUnits, float2 renderTargetSize, float dpi)
+{
+ float2 origin;
+ if (positionUnits == PositionUnits::Pixels)
+ {
+ origin.x = (position.x / renderTargetSize.x) * 2.0f - 1.0f;
+ origin.y = 1.0f - (position.y / renderTargetSize.y) * 2.0f;
+ }
+ else if (positionUnits == PositionUnits::DIPs)
+ {
+ origin.x = ((position.x * dpi / 96.0f) / renderTargetSize.x) * 2.0f - 1.0f;
+ origin.y = 1.0f - ((position.y * dpi / 96.0f) / renderTargetSize.y) * 2.0f;
+ }
+ else if (positionUnits == PositionUnits::Normalized)
+ {
+ origin.x = position.x * 2.0f - 1.0f;
+ origin.y = 1.0f - position.y * 2.0f;
+ }
+ else if (positionUnits == PositionUnits::UniformWidth)
+ {
+ origin.x = position.x * 2.0f - 1.0f;
+ origin.y = 1.0f - position.y * (renderTargetSize.x / renderTargetSize.y) * 2.0f;
+ }
+ else if (positionUnits == PositionUnits::UniformHeight)
+ {
+ origin.x = position.x * (renderTargetSize.y / renderTargetSize.x) * 2.0f - 1.0f;
+ origin.y = 1.0f - position.y * 2.0f;
+ }
+ return origin;
+}
+
+float2 SpriteBatch::StandardOffset(float2 size, SizeUnits sizeUnits, float2 spriteSize, float dpi)
+{
+ float2 offset;
+ if (sizeUnits == SizeUnits::Pixels)
+ {
+ offset = size;
+ }
+ else if (sizeUnits == SizeUnits::DIPs)
+ {
+ offset = size * dpi / 96.0f;
+ }
+ else if (sizeUnits == SizeUnits::Normalized)
+ {
+ offset = spriteSize * size;
+ }
+ return offset;
+}
+
+void SpriteBatch::Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits = PositionUnits::DIPs
+ )
+{
+ Draw(
+ texture,
+ position,
+ positionUnits,
+ float2(1.0f, 1.0f),
+ SizeUnits::Normalized
+ );
+}
+
+void SpriteBatch::Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits
+ )
+{
+ Draw(
+ texture,
+ position,
+ positionUnits,
+ size,
+ sizeUnits,
+ float4(1.0f, 1.0f, 1.0f, 1.0f)
+ );
+}
+
+void SpriteBatch::Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color
+ )
+{
+ Draw(
+ texture,
+ position,
+ positionUnits,
+ size,
+ sizeUnits,
+ color,
+ 0.0f
+ );
+}
+
+void SpriteBatch::Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color,
+ _In_ float rotation
+ )
+{
+ Draw(
+ texture,
+ position,
+ positionUnits,
+ size,
+ sizeUnits,
+ color,
+ rotation,
+ BlendMode::Alpha
+ );
+}
+
+void SpriteBatch::Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color,
+ _In_ float rotation,
+ _In_ BlendMode blendMode
+ )
+{
+ // Fail if drawing this sprite would exceed the capacity of the sprite batch.
+ if (m_numSpritesDrawn >= m_capacity)
+ {
+ throw ref new Platform::OutOfBoundsException();
+ }
+
+ // Retrieve information about the sprite.
+ TextureMapElement element = m_textureMap[texture];
+ ID3D11ShaderResourceView* textureView = element.srv.Get();
+ float2 textureSize = element.size;
+ ID3D11BlendState1* blendState = blendMode == BlendMode::Additive ? m_blendStateAdditive.Get() : m_blendStateAlpha.Get();
+
+ // Fail if the texture has not previously been added to the sprite batch.
+ if (textureView == nullptr)
+ {
+ throw ref new Platform::NullReferenceException();
+ }
+
+ // Unless this is the first sprite run, save out the previous run info if a new run is required.
+ if (
+ m_numSpritesDrawn > 0 && (
+ textureView != m_currentTextureView ||
+ blendState != m_currentBlendState
+ )
+ )
+ {
+ SpriteRunInfo runInfo;
+ runInfo.textureView = m_currentTextureView;
+ runInfo.blendState = m_currentBlendState;
+ runInfo.numSprites = m_spritesInRun;
+ m_spriteRuns.push_back(runInfo);
+ m_spritesInRun = 0; // Reset for the next sprite run.
+ }
+ m_currentTextureView = textureView;
+ m_currentBlendState = blendState;
+
+ // Add the sprite to the buffer.
+
+ float2 origin = StandardOrigin(position, positionUnits, m_renderTargetSize, m_dpi);
+ float2 offset = StandardOffset(size, sizeUnits, textureSize, m_dpi);
+
+ if (m_technique == RenderTechnique::GeometryShader || m_technique == RenderTechnique::Instancing)
+ {
+ m_instanceData[m_numSpritesDrawn].origin = origin;
+ m_instanceData[m_numSpritesDrawn].offset = offset;
+ m_instanceData[m_numSpritesDrawn].rotation = rotation;
+ m_instanceData[m_numSpritesDrawn].color = MakeUnorm(color);
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ float2 offsets[4] =
+ {
+ float2(-offset.x, offset.y),
+ float2( offset.x, offset.y),
+ float2(-offset.x, -offset.y),
+ float2( offset.x, -offset.y)
+ };
+
+ float sinRotation = sinf(rotation);
+ float cosRotation = cosf(rotation);
+
+ for (int i = 0; i < 4; i++)
+ {
+ offsets[i] = float2(
+ offsets[i].x * cosRotation - offsets[i].y * sinRotation,
+ offsets[i].x * sinRotation + offsets[i].y * cosRotation
+ );
+ offsets[i].x /= m_renderTargetSize.x;
+ offsets[i].y /= m_renderTargetSize.y;
+ }
+
+ // Write vertex buffer data.
+
+ ReplicationVertex* singleSpriteVertices = &m_vertexData[m_numSpritesDrawn * 4];
+ unsigned int colorUnorm = MakeUnorm(color);
+ singleSpriteVertices[0].pos = origin + offsets[0];
+ singleSpriteVertices[1].pos = origin + offsets[1];
+ singleSpriteVertices[2].pos = origin + offsets[2];
+ singleSpriteVertices[3].pos = origin + offsets[3];
+ singleSpriteVertices[0].color = colorUnorm;
+ singleSpriteVertices[1].color = colorUnorm;
+ singleSpriteVertices[2].color = colorUnorm;
+ singleSpriteVertices[3].color = colorUnorm;
+ singleSpriteVertices[0].tex = float2(0.0f, 0.0f);
+ singleSpriteVertices[1].tex = float2(1.0f, 0.0f);
+ singleSpriteVertices[2].tex = float2(0.0f, 1.0f);
+ singleSpriteVertices[3].tex = float2(1.0f, 1.0f);
+ }
+
+ m_spritesInRun++;
+ m_numSpritesDrawn++;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "BasicMath.h"
+#include <vector>
+#include <map>
+#include <memory>
+
+namespace BasicSprites
+{
+ namespace Parameters
+ {
+ // The index buffer format for feature-level 9.1 devices may only be 16 bits.
+ // With 4 vertices per sprite, this allows a maximum of (1 << 16) / 4 sprites.
+ static unsigned int MaximumCapacityCompatible = (1 << 16) / 4;
+ }
+
+ enum class PositionUnits
+ {
+ DIPs, // Interpret position as device-independent pixel values.
+ Pixels, // Interpret position as pixel values.
+ Normalized, // Interpret position as a fraction of the render target dimensions.
+ UniformWidth, // Interpret position as a fraction of the render target width.
+ UniformHeight // Interpret position as a fraction of the render target height.
+ };
+
+ enum class SizeUnits
+ {
+ DIPs, // Interpret size as device-independent pixel values.
+ Pixels, // Interpret size as pixel values.
+ Normalized // Interpret size as a multiplier of the pixel size of the sprite.
+ };
+
+ enum class BlendMode
+ {
+ Alpha, // Use alpha blending (out = old * (1 - new.a) + new * new.a).
+ Additive // Use additive blending (out = old + new * new.a).
+ };
+
+ enum class RenderTechnique
+ {
+ Replication,
+ Instancing,
+ GeometryShader
+ };
+
+ struct ReplicationVertex
+ {
+ float2 pos;
+ float2 tex;
+ unsigned int color;
+ };
+
+ struct InstancingVertex
+ {
+ float2 pos;
+ float2 tex;
+ };
+
+ struct InstanceData
+ {
+ float2 origin;
+ float2 offset;
+ float rotation;
+ unsigned int color;
+ };
+
+ struct TextureMapElement
+ {
+ Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> srv;
+ float2 size;
+ };
+
+ struct SpriteRunInfo
+ {
+ ID3D11ShaderResourceView* textureView;
+ ID3D11BlendState1* blendState;
+ unsigned int numSprites;
+ };
+
+ ref class SpriteBatch
+ {
+ public:
+ SpriteBatch();
+ void Initialize(
+ _In_ ID3D11Device1* d3dDevice,
+ _In_ int capacity
+ );
+ void AddTexture(
+ _In_ ID3D11Texture2D* texture
+ );
+ void RemoveTexture(
+ _In_ ID3D11Texture2D* texture
+ );
+ void Begin();
+ void End();
+ void Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits
+ );
+ void Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits
+ );
+ void Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color
+ );
+ void Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color,
+ _In_ float rotation
+ );
+ void Draw(
+ _In_ ID3D11Texture2D* texture,
+ _In_ float2 position,
+ _In_ PositionUnits positionUnits,
+ _In_ float2 size,
+ _In_ SizeUnits sizeUnits,
+ _In_ float4 color,
+ _In_ float rotation,
+ _In_ BlendMode blendMode
+ );
+
+ private:
+ unsigned int MakeUnorm(float4 color);
+ float2 StandardOrigin(float2 position, PositionUnits positionUnits, float2 renderTargetSize, float dpi);
+ float2 StandardOffset(float2 size, SizeUnits sizeUnits, float2 spriteSize, float dpi);
+
+ Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
+ Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_instanceDataBuffer;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_indexBuffer;
+ Microsoft::WRL::ComPtr<ID3D11BlendState1> m_blendStateAlpha;
+ Microsoft::WRL::ComPtr<ID3D11BlendState1> m_blendStateAdditive;
+ Microsoft::WRL::ComPtr<ID3D11InputLayout> m_inputLayout;
+ Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vertexShader;
+ Microsoft::WRL::ComPtr<ID3D11GeometryShader> m_geometryShader;
+ Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pixelShader;
+ Microsoft::WRL::ComPtr<ID3D11SamplerState> m_linearSampler;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_renderTargetInfoCbuffer;
+
+ std::unique_ptr<ReplicationVertex[]> m_vertexData;
+ std::unique_ptr<InstanceData[]> m_instanceData;
+ std::map<ID3D11Texture2D*, TextureMapElement> m_textureMap;
+ std::vector<SpriteRunInfo> m_spriteRuns;
+
+ RenderTechnique m_technique;
+ ID3D11ShaderResourceView* m_currentTextureView;
+ ID3D11BlendState1* m_currentBlendState;
+ float2 m_renderTargetSize;
+ int m_capacity;
+ int m_spritesInRun;
+ int m_numSpritesDrawn;
+ float m_dpi;
+ };
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//----------------------------------------------------------------------
+
+Texture2D spriteTexture : register(t0);
+SamplerState linearSampler : register(s0);
+
+struct PixelShaderInput
+{
+ float4 pos : SV_POSITION;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+// This general-purpose pixel shader draws a bound texture with optionally modified color channels.
+
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+ return input.color * spriteTexture.Sample(linearSampler, input.tex);
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "BasicTimer.h"
+
+BasicTimer::BasicTimer()
+{
+ if (!QueryPerformanceFrequency(&m_frequency))
+ {
+ throw ref new Platform::FailureException();
+ }
+ Reset();
+}
+
+void BasicTimer::Reset()
+{
+ Update();
+ m_startTime = m_currentTime;
+ m_total = 0.0f;
+ m_delta = 1.0f / 60.0f;
+}
+
+void BasicTimer::Update()
+{
+ if (!QueryPerformanceCounter(&m_currentTime))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ m_total = static_cast<float>(
+ static_cast<double>(m_currentTime.QuadPart-m_startTime.QuadPart) /
+ static_cast<double>(m_frequency.QuadPart)
+ );
+
+ if (m_lastTime.QuadPart==m_startTime.QuadPart)
+ {
+ // If the timer was just reset, report a time delta equivalent to 60Hz frame time.
+ m_delta = 1.0f / 60.0f;
+ }
+ else
+ {
+ m_delta = static_cast<float>(
+ static_cast<double>(m_currentTime.QuadPart-m_lastTime.QuadPart) /
+ static_cast<double>(m_frequency.QuadPart)
+ );
+ }
+
+ m_lastTime = m_currentTime;
+}
+
+float BasicTimer::Total::get()
+{
+ return m_total;
+}
+
+float BasicTimer::Delta::get()
+{
+ return m_delta;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+ref class BasicTimer
+{
+private:
+ LARGE_INTEGER m_frequency;
+ LARGE_INTEGER m_currentTime;
+ LARGE_INTEGER m_startTime;
+ LARGE_INTEGER m_lastTime;
+ float m_total;
+ float m_delta;
+
+public:
+ BasicTimer();
+ void Reset();
+ void Update();
+ property float Total
+ {
+ float get();
+ }
+ property float Delta
+ {
+ float get();
+ }
+};
+++ /dev/null
-<Page
- x:Class="ShootingGame.BlankPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:ShootingGame"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d">
-
- <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
-
- </Grid>
-</Page>
--- /dev/null
+//--------------------------------------------------------------------------------------
+// File: DDSTextureLoader.cpp
+//
+// Function for loading a DDS texture and creating a Direct3D 11 runtime resource for it
+//
+// Note this function is useful as a light-weight runtime loader for DDS files. For
+// a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+#include "pch.h"
+#include <dxgiformat.h>
+#include <assert.h>
+#include <memory>
+#include "DDSTextureLoader.h"
+#include "DirectXSample.h"
+
+using namespace Microsoft::WRL;
+
+//--------------------------------------------------------------------------------------
+// Macros
+//--------------------------------------------------------------------------------------
+#ifndef MAKEFOURCC
+ #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((uint32)(byte)(ch0) | ((uint32)(byte)(ch1) << 8) | \
+ ((uint32)(byte)(ch2) << 16) | ((uint32)(byte)(ch3) << 24 ))
+#endif /* defined(MAKEFOURCC) */
+
+//--------------------------------------------------------------------------------------
+// DDS file structure definitions
+//
+// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
+//--------------------------------------------------------------------------------------
+#pragma pack(push,1)
+
+#define DDS_MAGIC 0x20534444 // "DDS "
+
+struct DDS_PIXELFORMAT
+{
+ uint32 size;
+ uint32 flags;
+ uint32 fourCC;
+ uint32 RGBBitCount;
+ uint32 RBitMask;
+ uint32 GBitMask;
+ uint32 BBitMask;
+ uint32 ABitMask;
+};
+
+#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
+#define DDS_RGB 0x00000040 // DDPF_RGB
+#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
+#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
+#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
+#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
+#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
+
+#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
+#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
+#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
+#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
+#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
+
+#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
+#define DDS_WIDTH 0x00000004 // DDSD_WIDTH
+
+#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
+#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
+#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
+
+#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
+#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
+#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
+#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
+#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
+#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
+
+#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
+ DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
+ DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
+
+#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
+
+#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
+
+typedef struct
+{
+ uint32 size;
+ uint32 flags;
+ uint32 height;
+ uint32 width;
+ uint32 pitchOrLinearSize;
+ uint32 depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
+ uint32 mipMapCount;
+ uint32 reserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ uint32 caps;
+ uint32 caps2;
+ uint32 caps3;
+ uint32 caps4;
+ uint32 reserved2;
+} DDS_HEADER;
+
+typedef struct
+{
+ DXGI_FORMAT dxgiFormat;
+ uint32 resourceDimension;
+ uint32 miscFlag; // see D3D11_RESOURCE_MISC_FLAG
+ uint32 arraySize;
+ uint32 reserved;
+} DDS_HEADER_DXT10;
+
+#pragma pack(pop)
+
+//--------------------------------------------------------------------------------------
+// Return the BPP for a particular format
+//--------------------------------------------------------------------------------------
+static size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
+{
+ switch( fmt )
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return 128;
+
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 96;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return 64;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return 32;
+
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return 16;
+
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return 8;
+
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return 4;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 8;
+
+ default:
+ return 0;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Get surface information for a particular format
+//--------------------------------------------------------------------------------------
+static void GetSurfaceInfo( _In_ size_t width,
+ _In_ size_t height,
+ _In_ DXGI_FORMAT fmt,
+ _Out_opt_ size_t* outNumBytes,
+ _Out_opt_ size_t* outRowBytes,
+ _Out_opt_ size_t* outNumRows )
+{
+ size_t numBytes = 0;
+ size_t rowBytes = 0;
+ size_t numRows = 0;
+
+ bool bc = false;
+ bool packed = false;
+ size_t bcnumBytesPerBlock = 0;
+ switch (fmt)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ bc=true;
+ bcnumBytesPerBlock = 8;
+ break;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ bc = true;
+ bcnumBytesPerBlock = 16;
+ break;
+
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ packed = true;
+ break;
+ }
+
+ if (bc)
+ {
+ size_t numBlocksWide = 0;
+ if (width > 0)
+ {
+ numBlocksWide = max( 1, (width + 3) / 4 );
+ }
+ size_t numBlocksHigh = 0;
+ if (height > 0)
+ {
+ numBlocksHigh = max( 1, (height + 3) / 4 );
+ }
+ rowBytes = numBlocksWide * bcnumBytesPerBlock;
+ numRows = numBlocksHigh;
+ }
+ else if (packed)
+ {
+ rowBytes = ( ( width + 1 ) >> 1 ) * 4;
+ numRows = height;
+ }
+ else
+ {
+ size_t bpp = BitsPerPixel( fmt );
+ rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
+ numRows = height;
+ }
+
+ numBytes = rowBytes * numRows;
+ if (outNumBytes)
+ {
+ *outNumBytes = numBytes;
+ }
+ if (outRowBytes)
+ {
+ *outRowBytes = rowBytes;
+ }
+ if (outNumRows)
+ {
+ *outNumRows = numRows;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+#define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a )
+
+static DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf )
+{
+ if (ddpf.flags & DDS_RGB)
+ {
+ // Note that sRGB formats are written using the "DX10" extended header
+
+ switch (ddpf.RGBBitCount)
+ {
+ case 32:
+ if (ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000))
+ {
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000))
+ {
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000))
+ {
+ return DXGI_FORMAT_B8G8R8X8_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8
+
+ // Note that many common DDS reader/writers (including D3DX) swap the
+ // the RED/BLUE masks for 10:10:10:2 formats. We assumme
+ // below that the 'backwards' header mask is being used since it is most
+ // likely written by D3DX. The more robust solution is to use the 'DX10'
+ // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
+
+ // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data
+ if (ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000))
+ {
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10
+
+ if (ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R16G16_UNORM;
+ }
+
+ if (ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000))
+ {
+ // Only 32-bit color channel format in D3D9 was R32F
+ return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
+ }
+ break;
+
+ case 24:
+ // No 24bpp DXGI formats aka D3DFMT_R8G8B8
+ break;
+
+ case 16:
+ if (ISBITMASK(0x7c00,0x03e0,0x001f,0x8000))
+ {
+ return DXGI_FORMAT_B5G5R5A1_UNORM;
+ }
+ if (ISBITMASK(0xf800,0x07e0,0x001f,0x0000))
+ {
+ return DXGI_FORMAT_B5G6R5_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
+ if (ISBITMASK(0x0f00,0x00f0,0x000f,0xf000))
+ {
+ return DXGI_FORMAT_B4G4R4A4_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
+
+ // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
+ break;
+ }
+ }
+ else if (ddpf.flags & DDS_LUMINANCE)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4
+ }
+
+ if (16 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x0000ffff,0x00000000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00))
+ {
+ return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ }
+ }
+ else if (ddpf.flags & DDS_ALPHA)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ return DXGI_FORMAT_A8_UNORM;
+ }
+ }
+ else if (ddpf.flags & DDS_FOURCC)
+ {
+ if (MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC1_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
+ // they are basically the same as these BC formats so they can be mapped
+ if (MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ if (MAKEFOURCC( 'A', 'T', 'I', '1' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '4', 'U' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '4', 'S' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_SNORM;
+ }
+
+ if (MAKEFOURCC( 'A', 'T', 'I', '2' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '5', 'U' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '5', 'S' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_SNORM;
+ }
+
+ // BC6H and BC7 are written using the "DX10" extended header
+
+ if (MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_R8G8_B8G8_UNORM;
+ }
+ if (MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_G8R8_G8B8_UNORM;
+ }
+
+ // Check for D3DFORMAT enums being set here
+ switch( ddpf.fourCC )
+ {
+ case 36: // D3DFMT_A16B16G16R16
+ return DXGI_FORMAT_R16G16B16A16_UNORM;
+
+ case 110: // D3DFMT_Q16W16V16U16
+ return DXGI_FORMAT_R16G16B16A16_SNORM;
+
+ case 111: // D3DFMT_R16F
+ return DXGI_FORMAT_R16_FLOAT;
+
+ case 112: // D3DFMT_G16R16F
+ return DXGI_FORMAT_R16G16_FLOAT;
+
+ case 113: // D3DFMT_A16B16G16R16F
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ case 114: // D3DFMT_R32F
+ return DXGI_FORMAT_R32_FLOAT;
+
+ case 115: // D3DFMT_G32R32F
+ return DXGI_FORMAT_R32G32_FLOAT;
+
+ case 116: // D3DFMT_A32B32G32R32F
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ }
+ }
+
+ return DXGI_FORMAT_UNKNOWN;
+}
+
+
+//--------------------------------------------------------------------------------------
+static void FillInitData( _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ size_t maxsize,
+ _In_ size_t bitSize,
+ _In_reads_bytes_(bitSize) const byte* bitData,
+ _Out_ size_t& twidth,
+ _Out_ size_t& theight,
+ _Out_ size_t& tdepth,
+ _Out_ size_t& skipMip,
+ _Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData )
+{
+ if ( !bitData || !initData )
+ throw ref new Platform::InvalidArgumentException();
+
+ skipMip = 0;
+ twidth = 0;
+ theight = 0;
+ tdepth = 0;
+
+ size_t NumBytes = 0;
+ size_t RowBytes = 0;
+ size_t NumRows = 0;
+ const byte* pSrcBits = bitData;
+ const byte* pEndBits = bitData + bitSize;
+
+ size_t index = 0;
+ for( size_t j = 0; j < arraySize; j++ )
+ {
+ size_t w = width;
+ size_t h = height;
+ size_t d = depth;
+ for( size_t i = 0; i < mipCount; i++ )
+ {
+ GetSurfaceInfo( w,
+ h,
+ format,
+ &NumBytes,
+ &RowBytes,
+ &NumRows
+ );
+
+ if ( (mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize) )
+ {
+ if ( !twidth )
+ {
+ twidth = w;
+ theight = h;
+ tdepth = d;
+ }
+
+ initData[index].pSysMem = ( const void* )pSrcBits;
+ initData[index].SysMemPitch = static_cast<UINT>( RowBytes );
+ initData[index].SysMemSlicePitch = static_cast<UINT>( NumBytes );
+ ++index;
+ }
+ else
+ ++skipMip;
+
+ if (pSrcBits + (NumBytes*d) > pEndBits)
+ {
+ throw ref new Platform::OutOfBoundsException();
+ }
+
+ pSrcBits += NumBytes * d;
+
+ w = w >> 1;
+ h = h >> 1;
+ d = d >> 1;
+ if (w == 0)
+ {
+ w = 1;
+ }
+ if (h == 0)
+ {
+ h = 1;
+ }
+ if (d == 0)
+ {
+ d = 1;
+ }
+ }
+ }
+
+ if ( !index )
+ throw ref new Platform::FailureException();
+}
+
+
+//--------------------------------------------------------------------------------------
+static HRESULT CreateD3DResources( _In_ ID3D11Device* d3dDevice,
+ _In_ uint32 resDim,
+ _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ bool isCubeMap,
+ _In_reads_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView )
+{
+ if ( !d3dDevice || !initData )
+ return E_INVALIDARG;
+
+ HRESULT hr = E_FAIL;
+
+ switch ( resDim )
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ D3D11_TEXTURE1D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.ArraySize = static_cast<UINT>( arraySize );
+ desc.Format = format;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture1D* tex = nullptr;
+ hr = d3dDevice->CreateTexture1D( &desc,
+ initData,
+ &tex
+ );
+ if (SUCCEEDED( hr ) && tex != 0)
+ {
+ if (textureView != 0)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ memset( &SRVDesc, 0, sizeof( SRVDesc ) );
+ SRVDesc.Format = format;
+
+ if (arraySize > 1)
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
+ SRVDesc.Texture1DArray.MipLevels = desc.MipLevels;
+ SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( arraySize );
+ }
+ else
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
+ SRVDesc.Texture1D.MipLevels = desc.MipLevels;
+ }
+
+ hr = d3dDevice->CreateShaderResourceView( tex,
+ &SRVDesc,
+ textureView
+ );
+ }
+
+ if (texture != 0)
+ {
+ *texture = tex;
+ }
+ else
+ {
+ tex->Release();
+ }
+ }
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.Height = static_cast<UINT>( height );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.ArraySize = static_cast<UINT>( arraySize );
+ desc.Format = format;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = (isCubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
+
+ ID3D11Texture2D* tex = nullptr;
+ hr = d3dDevice->CreateTexture2D( &desc,
+ initData,
+ &tex
+ );
+ if (SUCCEEDED( hr ) && tex != 0)
+ {
+ if (textureView != 0)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ memset( &SRVDesc, 0, sizeof( SRVDesc ) );
+ SRVDesc.Format = format;
+
+ if (isCubeMap)
+ {
+ if (arraySize > 6)
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
+ SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels;
+
+ // Earlier we set arraySize to (NumCubes * 6)
+ SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( arraySize / 6 );
+ }
+ else
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
+ SRVDesc.TextureCube.MipLevels = desc.MipLevels;
+ }
+ }
+ else if (arraySize > 1)
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
+ SRVDesc.Texture2DArray.MipLevels = desc.MipLevels;
+ SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( arraySize );
+ }
+ else
+ {
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
+ SRVDesc.Texture2D.MipLevels = desc.MipLevels;
+ }
+
+ hr = d3dDevice->CreateShaderResourceView( tex,
+ &SRVDesc,
+ textureView
+ );
+ }
+
+ if (texture != 0)
+ {
+ *texture = tex;
+ }
+ else
+ {
+ tex->Release();
+ }
+ }
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.Height = static_cast<UINT>( height );
+ desc.Depth = static_cast<UINT>( depth );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.Format = format;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture3D* tex = nullptr;
+ hr = d3dDevice->CreateTexture3D( &desc,
+ initData,
+ &tex
+ );
+ if (SUCCEEDED( hr ) && tex != 0)
+ {
+ if (textureView != 0)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ memset( &SRVDesc, 0, sizeof( SRVDesc ) );
+ SRVDesc.Format = format;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
+ SRVDesc.Texture3D.MipLevels = desc.MipLevels;
+
+ hr = d3dDevice->CreateShaderResourceView( tex,
+ &SRVDesc,
+ textureView
+ );
+ }
+
+ if (texture != 0)
+ {
+ *texture = tex;
+ }
+ else
+ {
+ tex->Release();
+ }
+ }
+ }
+ break;
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+static void CreateTextureFromDDS( _In_ ID3D11Device* d3dDevice,
+ _In_ const DDS_HEADER* header,
+ _In_reads_bytes_(bitSize) const byte* bitData,
+ _In_ size_t bitSize,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize )
+{
+ HRESULT hr = S_OK;
+
+ size_t width = header->width;
+ size_t height = header->height;
+ size_t depth = header->depth;
+
+ uint32 resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ size_t arraySize = 1;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ bool isCubeMap = false;
+
+ size_t mipCount = header->mipMapCount;
+ if (0 == mipCount)
+ {
+ mipCount = 1;
+ }
+
+ if ((header->ddspf.flags & DDS_FOURCC) &&
+ (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC ))
+ {
+ const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const char*)header + sizeof(DDS_HEADER) );
+
+ arraySize = d3d10ext->arraySize;
+ if (arraySize == 0)
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ if (BitsPerPixel( d3d10ext->dxgiFormat ) == 0)
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ format = d3d10ext->dxgiFormat;
+
+ switch ( d3d10ext->resourceDimension )
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ // D3DX writes 1D textures with a fixed Height of 1
+ if ((header->flags & DDS_HEIGHT) && height != 1)
+ {
+ throw ref new Platform::FailureException();
+ }
+ height = depth = 1;
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE)
+ {
+ arraySize *= 6;
+ isCubeMap = true;
+ }
+ depth = 1;
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ if (arraySize > 1)
+ {
+ throw ref new Platform::FailureException();
+ }
+ break;
+
+ default:
+ return throw ref new Platform::FailureException();
+ }
+
+ resDim = d3d10ext->resourceDimension;
+ }
+ else
+ {
+ format = GetDXGIFormat( header->ddspf );
+
+ if (format == DXGI_FORMAT_UNKNOWN)
+ {
+ return throw ref new Platform::FailureException();
+ }
+
+ if (header->flags & DDS_HEADER_FLAGS_VOLUME)
+ {
+ resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
+ }
+ else
+ {
+ if (header->caps2 & DDS_CUBEMAP)
+ {
+ // We require all six faces to be defined
+ if ((header->caps2 & DDS_CUBEMAP_ALLFACES ) != DDS_CUBEMAP_ALLFACES)
+ {
+ return throw ref new Platform::FailureException();
+ }
+
+ arraySize = 6;
+ isCubeMap = true;
+ }
+
+ depth = 1;
+ resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
+
+ // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
+ }
+
+ assert( BitsPerPixel( format ) != 0 );
+ }
+
+ // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
+ if (mipCount > D3D11_REQ_MIP_LEVELS)
+ {
+ return throw ref new Platform::FailureException();
+ }
+
+ switch ( resDim )
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURE1D_U_DIMENSION) )
+ {
+ return throw ref new Platform::FailureException();
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ if (isCubeMap)
+ {
+ // This is the right bound because we set arraySize to (NumCubes*6) above
+ if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURECUBE_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURECUBE_DIMENSION))
+ {
+ return throw ref new Platform::FailureException();
+ }
+ }
+ else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
+ (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
+ {
+ return throw ref new Platform::FailureException();
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ if ((arraySize > 1) ||
+ (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
+ (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
+ (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
+ {
+ return throw ref new Platform::FailureException();
+ }
+ break;
+ }
+
+ // Create the texture
+ std::unique_ptr<D3D11_SUBRESOURCE_DATA> initData( new D3D11_SUBRESOURCE_DATA[ mipCount * arraySize ] );
+
+ size_t skipMip = 0;
+ size_t twidth = 0;
+ size_t theight = 0;
+ size_t tdepth = 0;
+ FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
+ twidth, theight, tdepth, skipMip, initData.get() );
+
+ hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView );
+
+ if ( (hr == E_INVALIDARG) && !maxsize && (mipCount > 1) )
+ {
+ // Retry with a maxsize determined by feature level
+ switch( d3dDevice->GetFeatureLevel() )
+ {
+ case D3D_FEATURE_LEVEL_9_1:
+ case D3D_FEATURE_LEVEL_9_2:
+ if (isCubeMap)
+ {
+ maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
+ }
+ else
+ {
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+ : 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+ }
+ break;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+ : 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+ break;
+
+ default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
+ maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
+ : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+ break;
+ }
+
+ FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
+ twidth, theight, tdepth, skipMip, initData.get() );
+
+ hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, isCubeMap, initData.get(), texture, textureView );
+ }
+
+ DX::ThrowIfFailed(hr);
+}
+
+//--------------------------------------------------------------------------------------
+void CreateDDSTextureFromMemory( _In_ ID3D11Device* d3dDevice,
+ _In_reads_bytes_(ddsDataSize) const byte* ddsData,
+ _In_ size_t ddsDataSize,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize )
+{
+ if (!d3dDevice || !ddsData || (!texture && !textureView))
+ {
+ throw ref new Platform::InvalidArgumentException();
+ }
+
+ // Validate DDS file in memory
+ if (ddsDataSize < (sizeof(uint32) + sizeof(DDS_HEADER)))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ uint32 dwMagicNumber = *( const uint32* )( ddsData );
+ if (dwMagicNumber != DDS_MAGIC)
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ const DDS_HEADER* header = reinterpret_cast<const DDS_HEADER*>( ddsData + sizeof( uint32 ) );
+
+ // Verify header to validate DDS file
+ if (header->size != sizeof(DDS_HEADER) ||
+ header->ddspf.size != sizeof(DDS_PIXELFORMAT))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ // Check for DX10 extension
+ bool bDXT10Header = false;
+ if ((header->ddspf.flags & DDS_FOURCC) &&
+ (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC) )
+ {
+ // Must be long enough for both headers and magic value
+ if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32) + sizeof(DDS_HEADER_DXT10)))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ bDXT10Header = true;
+ }
+
+ ptrdiff_t offset = sizeof( uint32 )
+ + sizeof( DDS_HEADER )
+ + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0);
+
+ CreateTextureFromDDS( d3dDevice,
+ header,
+ ddsData + offset,
+ ddsDataSize - offset,
+ texture,
+ textureView,
+ maxsize
+ );
+}
--- /dev/null
+//--------------------------------------------------------------------------------------
+// File: DDSTextureLoader.h
+//
+// Function for loading a DDS texture and creating a Direct3D 11 runtime resource for it
+//
+// Note this function is useful as a light-weight runtime loader for DDS files. For
+// a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+#pragma once
+
+void CreateDDSTextureFromMemory(
+ _In_ ID3D11Device* d3dDevice,
+ _In_reads_bytes_(ddsDataSize) const byte* ddsData,
+ _In_ size_t ddsDataSize,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize = 0
+ );
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "DirectXBase.h"
+
+using namespace Windows::UI::Core;
+using namespace Windows::Foundation;
+using namespace Microsoft::WRL;
+using namespace D2D1;
+
+// Constructor.
+DirectXBase::DirectXBase() :
+ m_dpi(-1.0f)
+{
+}
+
+// Initialize the Direct3D resources required to run.
+void DirectXBase::Initialize(CoreWindow^ window, float dpi)
+{
+ m_window = window;
+
+ CreateDeviceIndependentResources();
+ CreateDeviceResources();
+ SetDpi(dpi);
+}
+
+// These are the resources required independent of hardware.
+void DirectXBase::CreateDeviceIndependentResources()
+{
+ D2D1_FACTORY_OPTIONS options;
+ ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
+
+#if defined(_DEBUG)
+ // If the project is in a debug build, enable Direct2D debugging via SDK Layers
+ options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+#endif
+
+ DX::ThrowIfFailed(
+ D2D1CreateFactory(
+ D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ __uuidof(ID2D1Factory1),
+ &options,
+ &m_d2dFactory
+ )
+ );
+
+ DX::ThrowIfFailed(
+ DWriteCreateFactory(
+ DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ &m_dwriteFactory
+ )
+ );
+
+ DX::ThrowIfFailed(
+ CoCreateInstance(
+ CLSID_WICImagingFactory,
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&m_wicFactory)
+ )
+ );
+}
+
+// These are the resources that depend on the device.
+void DirectXBase::CreateDeviceResources()
+{
+ // This flag adds support for surfaces with a different color channel ordering than the API default.
+ // It is recommended usage, and is required for compatibility with Direct2D.
+ UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+ ComPtr<IDXGIDevice> dxgiDevice;
+
+#if defined(_DEBUG)
+ // If the project is in a debug build, enable debugging via SDK Layers with this flag.
+ creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ // This array defines the set of DirectX hardware feature levels this app will support.
+ // Note the ordering should be preserved.
+ // Don't forget to declare your application's minimum required feature level in its
+ // description. All applications are assumed to support 9.1 unless otherwise stated.
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1
+ };
+
+ // Create the DX11 API device object, and get a corresponding context.
+ ComPtr<ID3D11Device> device;
+ ComPtr<ID3D11DeviceContext> context;
+ DX::ThrowIfFailed(
+ D3D11CreateDevice(
+ nullptr, // specify null to use the default adapter
+ D3D_DRIVER_TYPE_HARDWARE,
+ 0, // leave as 0 unless software device
+ creationFlags, // optionally set debug and Direct2D compatibility flags
+ featureLevels, // list of feature levels this app can support
+ ARRAYSIZE(featureLevels), // number of entries in above list
+ D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION for Metro style apps
+ &device, // returns the Direct3D device created
+ &m_featureLevel, // returns feature level of device created
+ &context // returns the device immediate context
+ )
+ );
+
+ // Get the DirectX11.1 device by QI off the DirectX11 one.
+ DX::ThrowIfFailed(
+ device.As(&m_d3dDevice)
+ );
+
+ // And get the corresponding device context in the same way.
+ DX::ThrowIfFailed(
+ context.As(&m_d3dContext)
+ );
+
+ // Obtain the underlying DXGI device of the Direct3D11.1 device.
+ DX::ThrowIfFailed(
+ m_d3dDevice.As(&dxgiDevice)
+ );
+
+ // Obtain the Direct2D device for 2-D rendering.
+ DX::ThrowIfFailed(
+ m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
+ );
+
+ // And get its corresponding device context object.
+ DX::ThrowIfFailed(
+ m_d2dDevice->CreateDeviceContext(
+ D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
+ &m_d2dContext
+ )
+ );
+
+ // Release the swap chain (if it exists) as it will be incompatible with
+ // the new device.
+ m_swapChain = nullptr;
+}
+
+// Helps track the DPI in the helper class.
+// This is called in the dpiChanged event handler in the view class.
+void DirectXBase::SetDpi(float dpi)
+{
+ if (dpi != m_dpi)
+ {
+ // Save the DPI of this display in our class.
+ m_dpi = dpi;
+
+ // Update Direct2D's stored DPI.
+ m_d2dContext->SetDpi(m_dpi, m_dpi);
+
+ // Often a DPI change implies a window size change. In some cases Windows will issues
+ // both a size changed event and a DPI changed event. In this case, the resulting bounds
+ // will not change, and the window resize code will only be executed once.
+ UpdateForWindowSizeChange();
+ }
+}
+
+// This routine is called in the event handler for the view SizeChanged event.
+void DirectXBase::UpdateForWindowSizeChange()
+{
+ if (m_window->Bounds.Width != m_windowBounds.Width ||
+ m_window->Bounds.Height != m_windowBounds.Height)
+ {
+ m_d2dContext->SetTarget(nullptr);
+ m_d2dTargetBitmap = nullptr;
+ m_renderTargetView = nullptr;
+ m_depthStencilView = nullptr;
+ CreateWindowSizeDependentResources();
+ }
+}
+
+// Allocate all memory resources that change on a window SizeChanged event.
+void DirectXBase::CreateWindowSizeDependentResources()
+{
+ // Store the window bounds so the next time we get a SizeChanged event we can
+ // avoid rebuilding everything if the size is identical.
+ m_windowBounds = m_window->Bounds;
+
+ // If the swap chain already exists, resize it.
+ if(m_swapChain != nullptr)
+ {
+ DX::ThrowIfFailed(
+ m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
+ );
+ }
+ // Otherwise, create a new one.
+ else
+ {
+ // Allocate a descriptor.
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = 0; // use automatic sizing
+ swapChainDesc.Height = 0;
+ swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
+ swapChainDesc.Stereo = false;
+ swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = 2; // use double buffering to enable flip
+ swapChainDesc.Scaling = DXGI_SCALING_NONE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all Metro style apps must use this SwapEffect
+ swapChainDesc.Flags = 0;
+
+ // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
+
+ // First, retrieve the underlying DXGI Device from the D3D Device.
+ ComPtr<IDXGIDevice1> dxgiDevice;
+ DX::ThrowIfFailed(
+ m_d3dDevice.As(&dxgiDevice)
+ );
+
+ // Identify the physical adapter (GPU or card) this device is running on.
+ ComPtr<IDXGIAdapter> dxgiAdapter;
+ DX::ThrowIfFailed(
+ dxgiDevice->GetAdapter(&dxgiAdapter)
+ );
+
+ // And obtain the factory object that created it.
+ ComPtr<IDXGIFactory2> dxgiFactory;
+ DX::ThrowIfFailed(
+ dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
+ );
+
+ // Obtain the final swap chain for this window from the DXGI factory.
+ DX::ThrowIfFailed(
+ dxgiFactory->CreateSwapChainForCoreWindow(
+ m_d3dDevice.Get(),
+ reinterpret_cast<IUnknown*>(m_window),
+ &swapChainDesc,
+ nullptr, // allow on all displays
+ &m_swapChain
+ )
+ );
+
+ // Ensure that DXGI does not queue more than one frame at a time. This both reduces
+ // latency and ensures that the application will only render after each VSync, minimizing
+ // power consumption.
+ DX::ThrowIfFailed(
+ dxgiDevice->SetMaximumFrameLatency(1)
+ );
+
+ }
+
+ // Obtain the backbuffer for this window which will be the final 3D rendertarget.
+ ComPtr<ID3D11Texture2D> backBuffer;
+ DX::ThrowIfFailed(
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
+ );
+
+ // Create a view interface on the rendertarget to use on bind.
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateRenderTargetView(
+ backBuffer.Get(),
+ nullptr,
+ &m_renderTargetView
+ )
+ );
+
+ // Cache the rendertarget dimensions in our helper class for convenient use.
+ D3D11_TEXTURE2D_DESC backBufferDesc = {0};
+ backBuffer->GetDesc(&backBufferDesc);
+ m_renderTargetSize.Width = static_cast<float>(backBufferDesc.Width);
+ m_renderTargetSize.Height = static_cast<float>(backBufferDesc.Height);
+
+ // Create a descriptor for the depth/stencil buffer.
+ CD3D11_TEXTURE2D_DESC depthStencilDesc(
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ backBufferDesc.Width,
+ backBufferDesc.Height,
+ 1,
+ 1,
+ D3D11_BIND_DEPTH_STENCIL
+ );
+
+ // Allocate a 2-D surface as the depth/stencil buffer.
+ ComPtr<ID3D11Texture2D> depthStencil;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateTexture2D(
+ &depthStencilDesc,
+ nullptr,
+ &depthStencil
+ )
+ );
+
+ // Create a DepthStencil view on this surface to use on bind.
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDepthStencilView(
+ depthStencil.Get(),
+ &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
+ &m_depthStencilView
+ )
+ );
+
+ // Create a viewport descriptor of the full window size.
+ CD3D11_VIEWPORT viewport(
+ 0.0f,
+ 0.0f,
+ static_cast<float>(backBufferDesc.Width),
+ static_cast<float>(backBufferDesc.Height)
+ );
+
+ // Set the current viewport using the descriptor.
+ m_d3dContext->RSSetViewports(1, &viewport);
+
+ // Now we set up the Direct2D render target bitmap linked to the swapchain.
+ // Whenever we render to this bitmap, it will be directly rendered to the
+ // swapchain associated with the window.
+ D2D1_BITMAP_PROPERTIES1 bitmapProperties =
+ BitmapProperties1(
+ D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
+ PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
+ m_dpi,
+ m_dpi
+ );
+
+ // Direct2D needs the dxgi version of the backbuffer surface pointer.
+ ComPtr<IDXGISurface> dxgiBackBuffer;
+ DX::ThrowIfFailed(
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
+ );
+
+ // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
+ DX::ThrowIfFailed(
+ m_d2dContext->CreateBitmapFromDxgiSurface(
+ dxgiBackBuffer.Get(),
+ &bitmapProperties,
+ &m_d2dTargetBitmap
+ )
+ );
+
+ // So now we can set the Direct2D render target.
+ m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
+
+ // Set D2D text anti-alias mode to Grayscale to ensure proper rendering of text on intermediate surfaces.
+ m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
+}
+
+// Method to deliver the final image to the display.
+void DirectXBase::Present()
+{
+ // The application may optionally specify "dirty" or "scroll" rects to improve efficiency
+ // in certain scenarios. In this sample, however, we do not utilize those features.
+ DXGI_PRESENT_PARAMETERS parameters = {0};
+ parameters.DirtyRectsCount = 0;
+ parameters.pDirtyRects = nullptr;
+ parameters.pScrollRect = nullptr;
+ parameters.pScrollOffset = nullptr;
+
+ // The first argument instructs DXGI to block until VSync, putting the application
+ // to sleep until the next VSync. This ensures we don't waste any cycles rendering
+ // frames that will never be displayed to the screen.
+ HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
+
+ // If the device was removed either by a disconnect or a driver upgrade, we
+ // must completely reinitialize the renderer.
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
+ {
+ Initialize(m_window, m_dpi);
+ }
+ else
+ {
+ DX::ThrowIfFailed(hr);
+ }
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "DirectXSample.h"
+
+#pragma warning (disable: 4449) // warns that class is not consumable by JS because it is not sealed
+
+// Helper class that initializes the DirectX APIs in the sample apps.
+public ref class DirectXBase abstract
+{
+public:
+ DirectXBase();
+
+ virtual void Initialize(Windows::UI::Core::CoreWindow^ window, float dpi);
+ virtual void CreateDeviceIndependentResources();
+ virtual void CreateDeviceResources();
+ virtual void SetDpi(float dpi);
+ virtual void UpdateForWindowSizeChange();
+ virtual void CreateWindowSizeDependentResources();
+ virtual void Render() = 0;
+ virtual void Present();
+
+protected:
+
+ Windows::UI::Core::CoreWindow^ m_window;
+
+ // Declare Direct2D Objects
+ Microsoft::WRL::ComPtr<ID2D1Factory1> m_d2dFactory;
+ Microsoft::WRL::ComPtr<ID2D1Device> m_d2dDevice;
+ Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_d2dContext;
+ Microsoft::WRL::ComPtr<ID2D1Bitmap1> m_d2dTargetBitmap;
+
+ // Declare DirectWrite & Windows Imaging Component Objects
+ Microsoft::WRL::ComPtr<IDWriteFactory1> m_dwriteFactory;
+ Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
+
+ // Direct3D Objects
+ Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
+ Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
+ Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
+ Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_renderTargetView;
+ Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_depthStencilView;
+
+ D3D_FEATURE_LEVEL m_featureLevel;
+ Windows::Foundation::Size m_renderTargetSize;
+ Windows::Foundation::Rect m_windowBounds;
+ float m_dpi;
+};
+
+
+#pragma warning (default: 4449)
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+// Helper utilities to make DX APIs work with exceptions in the samples apps.
+namespace DX
+{
+ inline void ThrowIfFailed(HRESULT hr)
+ {
+ if (FAILED(hr))
+ {
+ // Set a breakpoint on this line to catch DX API errors.
+ throw Platform::Exception::CreateException(hr);
+ }
+ }
+}
--- /dev/null
+<SwapChainBackgroundPanel
+ x:Class="ShootingGame.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:ShootingGame"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d">
+ <TextBox HorizontalAlignment="Left" Height="50" Margin="316,161,0,0" TextWrapping="Wrap" Text="テストテキストボックスとか" VerticalAlignment="Top" Width="335"/>
+ <Button Content="Button" HorizontalAlignment="Left" Height="50" Margin="692,161,0,0" VerticalAlignment="Top" Width="205"/>
+</SwapChainBackgroundPanel>
//
-//BlankPage.xaml.cpp
-//BlankPage.xaml クラスの実装。
+//MainPage.xaml.cpp
+//MainPage.xaml クラスの実装。
//
#include "pch.h"
-#include "BlankPage.xaml.h"
+#include "MainPage.xaml.h"
using namespace ShootingGame;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
-BlankPage::BlankPage()
+MainPage::MainPage()
{
InitializeComponent();
}
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
-void BlankPage::OnNavigatedTo(NavigationEventArgs^ e)
+void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
}
//
-//BlankPage.xaml.h
-//BlankPage.xaml クラスの宣言。
+//MainPage.xaml.h
+//MainPage.xaml クラスの宣言。
//
#pragma once
#include "pch.h"
-#include "BlankPage.g.h"
+#include "MainPage.g.h"
namespace ShootingGame
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
- public ref class BlankPage sealed
+ public ref class MainPage sealed
{
public:
- BlankPage();
+ MainPage();
protected:
virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "SampleOverlay.h"
+
+using namespace Windows::UI::Core;
+using namespace Windows::Foundation;
+using namespace Microsoft::WRL;
+using namespace Windows::UI::ViewManagement;
+using namespace Windows::Graphics::Display;
+using namespace D2D1;
+
+SampleOverlay::SampleOverlay() :
+ m_drawOverlay(true)
+{
+}
+
+void SampleOverlay::Initialize(
+ _In_ ID2D1Device* d2dDevice,
+ _In_ ID2D1DeviceContext* d2dContext,
+ _In_ IWICImagingFactory* wicFactory,
+ _In_ IDWriteFactory* dwriteFactory,
+ _In_ Platform::String^ caption
+ )
+{
+ m_wicFactory = wicFactory;
+ m_dwriteFactory = dwriteFactory;
+ m_sampleName = caption;
+ m_d2dDevice = d2dDevice;
+ m_d2dContext = d2dContext;
+ m_padding = 3.0f;
+ m_textVerticalOffset = 5.0f;
+ m_logoSize = D2D1::SizeF(0.0f, 0.0f);
+ m_overlayWidth = 0.0f;
+
+ ComPtr<ID2D1Factory> factory;
+ d2dDevice->GetFactory(&factory);
+
+ DX::ThrowIfFailed(
+ factory.As(&m_d2dFactory)
+ );
+
+ ResetDirectXResources();
+}
+
+void SampleOverlay::ResetDirectXResources()
+{
+ DX::ThrowIfFailed(
+ m_d2dContext->CreateSolidColorBrush(ColorF(ColorF::White), &m_whiteBrush)
+ );
+
+ ComPtr<IWICBitmapDecoder> wicBitmapDecoder;
+ DX::ThrowIfFailed(
+ m_wicFactory->CreateDecoderFromFilename(
+ L"windowsbig-sdk.png",
+ nullptr,
+ GENERIC_READ,
+ WICDecodeMetadataCacheOnDemand,
+ &wicBitmapDecoder
+ )
+ );
+
+ ComPtr<IWICBitmapFrameDecode> wicBitmapFrame;
+ DX::ThrowIfFailed(
+ wicBitmapDecoder->GetFrame(0, &wicBitmapFrame)
+ );
+
+ ComPtr<IWICFormatConverter> wicFormatConverter;
+ DX::ThrowIfFailed(
+ m_wicFactory->CreateFormatConverter(&wicFormatConverter)
+ );
+
+ DX::ThrowIfFailed(
+ wicFormatConverter->Initialize(
+ wicBitmapFrame.Get(),
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.0,
+ WICBitmapPaletteTypeCustom // the BGRA format has no palette so this value is ignored
+ )
+ );
+
+ double dpiX = 96.0f;
+ double dpiY = 96.0f;
+ DX::ThrowIfFailed(
+ wicFormatConverter->GetResolution(&dpiX, &dpiY)
+ );
+
+ DX::ThrowIfFailed(
+ m_d2dContext->CreateBitmapFromWicBitmap(
+ wicFormatConverter.Get(),
+ BitmapProperties(
+ PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
+ static_cast<float>(dpiX),
+ static_cast<float>(dpiY)
+ ),
+ &m_logoBitmap
+ )
+ );
+
+ m_logoSize = m_logoBitmap->GetSize();
+
+ ComPtr<IDWriteTextFormat> nameTextFormat;
+ DX::ThrowIfFailed(
+ m_dwriteFactory->CreateTextFormat(
+ L"Segoe UI",
+ nullptr,
+ DWRITE_FONT_WEIGHT_LIGHT,
+ DWRITE_FONT_STYLE_NORMAL,
+ DWRITE_FONT_STRETCH_NORMAL,
+ 36.0f,
+ L"en-US",
+ &nameTextFormat
+ )
+ );
+
+ DX::ThrowIfFailed(
+ nameTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)
+ );
+
+ DX::ThrowIfFailed(
+ nameTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR)
+ );
+
+ DX::ThrowIfFailed(
+ m_dwriteFactory->CreateTextLayout(
+ m_sampleName->Data(),
+ m_sampleName->Length(),
+ nameTextFormat.Get(),
+ 4096.0f,
+ 4096.0f,
+ &m_textLayout
+ )
+ );
+
+ DWRITE_TEXT_METRICS metrics = {0};
+ DX::ThrowIfFailed(
+ m_textLayout->GetMetrics(&metrics)
+ );
+
+ m_overlayWidth = m_padding * 3.0f + m_logoSize.width + metrics.width;
+
+ DX::ThrowIfFailed(
+ m_d2dFactory->CreateDrawingStateBlock(&m_stateBlock)
+ );
+
+ UpdateForWindowSizeChange();
+}
+
+void SampleOverlay::UpdateForWindowSizeChange()
+{
+ if (CoreWindow::GetForCurrentThread()->Bounds.Width < m_overlayWidth)
+ {
+ m_drawOverlay = false;
+ }
+ else
+ {
+ m_drawOverlay = true;
+ }
+}
+
+void SampleOverlay::Render()
+{
+ if (m_drawOverlay)
+ {
+ m_d2dContext->SaveDrawingState(m_stateBlock.Get());
+
+ m_d2dContext->BeginDraw();
+ m_d2dContext->SetTransform(D2D1::Matrix3x2F::Identity());
+ m_d2dContext->DrawBitmap(
+ m_logoBitmap.Get(),
+ D2D1::RectF(m_padding, 0.0f, m_logoSize.width + m_padding, m_logoSize.height)
+ );
+
+ m_d2dContext->DrawTextLayout(
+ Point2F(m_logoSize.width + 2.0f * m_padding, m_textVerticalOffset),
+ m_textLayout.Get(),
+ m_whiteBrush.Get()
+ );
+
+ // We ignore the HRESULT returned as we want to application to handle the
+ // error when it uses Direct2D next.
+ m_d2dContext->EndDraw();
+
+ m_d2dContext->RestoreDrawingState(m_stateBlock.Get());
+ }
+}
+
+float SampleOverlay::GetTitleHeightInDips()
+{
+ return m_logoSize.height;
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "DirectXSample.h"
+
+ref class SampleOverlay
+{
+public:
+ SampleOverlay();
+
+ void Initialize(
+ _In_ ID2D1Device* d2dDevice,
+ _In_ ID2D1DeviceContext* d2dContext,
+ _In_ IWICImagingFactory* wicFactory,
+ _In_ IDWriteFactory* dwriteFactory,
+ _In_ Platform::String^ caption
+ );
+
+ void ResetDirectXResources();
+
+ void UpdateForWindowSizeChange();
+
+ void Render();
+
+ float GetTitleHeightInDips();
+
+private:
+
+ Microsoft::WRL::ComPtr<ID2D1Factory1> m_d2dFactory;
+ Microsoft::WRL::ComPtr<ID2D1Device> m_d2dDevice;
+ Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_d2dContext;
+ Microsoft::WRL::ComPtr<IDWriteFactory> m_dwriteFactory;
+ Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_whiteBrush;
+ Microsoft::WRL::ComPtr<ID2D1DrawingStateBlock> m_stateBlock;
+
+ Microsoft::WRL::ComPtr<IWICImagingFactory> m_wicFactory;
+ Microsoft::WRL::ComPtr<ID2D1Bitmap> m_logoBitmap;
+ Microsoft::WRL::ComPtr<IDWriteTextLayout> m_textLayout;
+
+ UINT m_idIncrement;
+ bool m_drawOverlay;
+ Platform::String^ m_sampleName;
+ float m_padding;
+ float m_textVerticalOffset;
+ D2D1_SIZE_F m_logoSize;
+ float m_overlayWidth;
+};
<PackageCertificateKeyFile>ShootingGame_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>10BE5E5F3DBAB946BEB360A653BF7E85DEDBF1A4</PackageCertificateThumbprint>
</PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <Link>
+ <AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <Link>
+ <AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="AutoThrottle.h" />
+ <ClInclude Include="BasicLoader.h" />
+ <ClInclude Include="BasicMath.h" />
+ <ClInclude Include="BasicReaderWriter.h" />
+ <ClInclude Include="BasicShapes.h" />
+ <ClInclude Include="BasicSprites.h" />
+ <ClInclude Include="BasicTimer.h" />
+ <ClInclude Include="DDSTextureLoader.h" />
+ <ClInclude Include="DirectXBase.h" />
+ <ClInclude Include="DirectXSample.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="Common\BindableBase.h" />
<ClInclude Include="Common\BooleanToVisibilityConverter.h" />
<ClInclude Include="App.xaml.h">
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
- <ClInclude Include="BlankPage.xaml.h">
- <DependentUpon>BlankPage.xaml</DependentUpon>
+ <ClInclude Include="MainPage.xaml.h">
+ <DependentUpon>MainPage.xaml</DependentUpon>
</ClInclude>
+ <ClInclude Include="SampleOverlay.h" />
+ <ClInclude Include="SimpleSprites.h" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Page Include="Common\StandardStyles.xaml">
<SubType>Designer</SubType>
</Page>
- <Page Include="BlankPage.xaml">
+ <Page Include="MainPage.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<Image Include="Assets\SmallLogo.png" />
<Image Include="Assets\StoreLogo.png" />
<Image Include="Assets\SplashScreen.png" />
+ <Image Include="ida.dds" />
+ <Image Include="m31.png" />
+ <Image Include="particle.dds" />
+ <Image Include="windowsbig-sdk.png" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="App.xaml.cpp">
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
+ <ClCompile Include="AutoThrottle.cpp" />
+ <ClCompile Include="BasicLoader.cpp" />
+ <ClCompile Include="BasicReaderWriter.cpp" />
+ <ClCompile Include="BasicSprites.cpp" />
+ <ClCompile Include="BasicTimer.cpp" />
<ClCompile Include="Common\BindableBase.cpp" />
<ClCompile Include="Common\BooleanToVisibilityConverter.cpp" />
<ClCompile Include="Common\BooleanNegationConverter.cpp" />
<ClCompile Include="Common\LayoutAwarePage.cpp" />
<ClCompile Include="Common\RichTextColumns.cpp" />
- <ClCompile Include="BlankPage.xaml.cpp">
- <DependentUpon>BlankPage.xaml</DependentUpon>
+ <ClCompile Include="DDSTextureLoader.cpp" />
+ <ClCompile Include="DirectXBase.cpp" />
+ <ClCompile Include="MainPage.xaml.cpp">
+ <DependentUpon>MainPage.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="SampleOverlay.cpp" />
+ <ClCompile Include="SimpleSprites.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <FxCompile Include="BasicSprites.GeometryShader.gs.hlsl">
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Geometry</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
+ </FxCompile>
+ <FxCompile Include="BasicSprites.GeometryShader.vs.hlsl">
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
+ </FxCompile>
+ <FxCompile Include="BasicSprites.Instancing.vs.hlsl">
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
+ </FxCompile>
+ <FxCompile Include="BasicSprites.ps.hlsl">
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
+ </FxCompile>
+ <FxCompile Include="BasicSprites.Replication.vs.hlsl">
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
+ </FxCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "pch.h"
+#include "SimpleSprites.h"
+#include "BasicLoader.h"
+#include "windows.ui.xaml.media.dxinterop.h"
+
+using namespace Microsoft::WRL;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::ViewManagement;
+
+using namespace Windows::UI::ApplicationSettings;
+using namespace Windows::UI::Popups;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::Graphics::Display;
+using namespace DirectX;
+using namespace D2D1;
+
+
+using namespace BasicSprites;
+
+SimpleSprites::SimpleSprites() :
+ m_numParticlesToDraw(SampleSettings::Performance::InitialParticleCount)
+{
+}
+
+void SimpleSprites::CreateDeviceIndependentResources()
+{
+ DirectXBase::CreateDeviceIndependentResources();
+
+ // Create the performance throttler.
+
+ m_autoThrottle = ref new AutoThrottle(SampleSettings::Performance::TargetFrameTime);
+}
+
+ void SimpleSprites::Initialize(
+ _In_ Windows::UI::Core::CoreWindow^ window,
+ _In_ Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ swapChainPanel,
+ _In_ float dpi
+ )
+ {
+ panel_ = swapChainPanel;
+ Initialize(window,dpi);
+ }
+
+void SimpleSprites::CreateDeviceResources()
+{
+ DirectXBase::CreateDeviceResources();
+
+ // Create the sprite batch.
+
+ m_spriteBatch = ref new SpriteBatch();
+ unsigned int capacity = SampleSettings::Performance::ParticleCountMax + SampleSettings::NumAsteroids + 1;
+ if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
+ {
+ capacity = min(Parameters::MaximumCapacityCompatible, capacity);
+ }
+ m_spriteBatch->Initialize(
+ m_d3dDevice.Get(),
+ capacity
+ );
+
+ // Load the sprite textures.
+
+ BasicLoader^ loader = ref new BasicLoader(m_d3dDevice.Get(), m_wicFactory.Get());
+
+ loader->LoadTexture(
+ "m31.png",
+ &m_background,
+ nullptr
+ );
+ m_spriteBatch->AddTexture(m_background.Get());
+
+ loader->LoadTexture(
+ "ida.dds",
+ &m_asteroid,
+ nullptr
+ );
+ m_spriteBatch->AddTexture(m_asteroid.Get());
+
+ loader->LoadTexture(
+ "particle.dds",
+ &m_particle,
+ nullptr
+ );
+ m_spriteBatch->AddTexture(m_particle.Get());
+
+ // Create the Sample Overlay.
+
+ m_sampleOverlay = ref new SampleOverlay();
+
+ m_sampleOverlay->Initialize(
+ m_d2dDevice.Get(),
+ m_d2dContext.Get(),
+ m_wicFactory.Get(),
+ m_dwriteFactory.Get(),
+ "Direct3D SpriteBatch sample"
+ );
+}
+
+void SimpleSprites::CreateWindowSizeDependentResources()
+{
+// DirectXBase::CreateWindowSizeDependentResources();
+ // Store the window bounds so the next time we get a SizeChanged event we can
+ // avoid rebuilding everything if the size is identical.
+ m_windowBounds = m_window->Bounds;
+
+ // If the swap chain already exists, resize it.
+ if(m_swapChain != nullptr)
+ {
+ DX::ThrowIfFailed(
+ m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
+ );
+ }
+ // Otherwise, create a new one.
+ else
+ {
+ // Allocate a descriptor.
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = static_cast<UINT>(m_window->Bounds.Width * m_dpi / 96.0f); // Can not use 0 to get the default on Composition SwapChain
+ swapChainDesc.Height = static_cast<UINT>(m_window->Bounds.Height * m_dpi / 96.0f);
+ swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
+ swapChainDesc.Stereo = false;
+ swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = 2; // use double buffering to enable flip
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all Metro style apps must use this SwapEffect
+ swapChainDesc.Flags = 0;
+
+ // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
+
+ // First, retrieve the underlying DXGI Device from the D3D Device.
+ ComPtr<IDXGIDevice1> dxgiDevice;
+ DX::ThrowIfFailed(
+ m_d3dDevice.As(&dxgiDevice)
+ );
+
+ // Identify the physical adapter (GPU or card) this device is running on.
+ ComPtr<IDXGIAdapter> dxgiAdapter;
+ DX::ThrowIfFailed(
+ dxgiDevice->GetAdapter(&dxgiAdapter)
+ );
+
+ // And obtain the factory object that created it.
+ ComPtr<IDXGIFactory2> dxgiFactory;
+ DX::ThrowIfFailed(
+ dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
+ );
+
+ // Obtain the final swap chain for this window from the DXGI factory.
+ DX::ThrowIfFailed(
+ dxgiFactory->CreateSwapChainForComposition(
+ m_d3dDevice.Get(),
+ &swapChainDesc,
+ nullptr, // allow on all displays
+ &m_swapChain
+ )
+ );
+
+ ComPtr<ISwapChainBackgroundPanelNative> dxRootPanelAsNative;
+
+ // set the swap chain on the SwapChainBackgroundPanel
+ reinterpret_cast<IUnknown*>(panel_)->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void**)&dxRootPanelAsNative);
+
+ DX::ThrowIfFailed(
+ dxRootPanelAsNative->SetSwapChain(m_swapChain.Get())
+ );
+
+ // Ensure that DXGI does not queue more than one frame at a time. This both reduces
+ // latency and ensures that the application will only render after each VSync, minimizing
+ // power consumption.
+ DX::ThrowIfFailed(
+ dxgiDevice->SetMaximumFrameLatency(1)
+ );
+
+ }
+
+ // Obtain the backbuffer for this window which will be the final 3D rendertarget.
+ ComPtr<ID3D11Texture2D> backBuffer;
+ DX::ThrowIfFailed(
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
+ );
+
+ // Create a view interface on the rendertarget to use on bind.
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateRenderTargetView(
+ backBuffer.Get(),
+ nullptr,
+ &m_renderTargetView
+ )
+ );
+
+ // Cache the rendertarget dimensions in our helper class for convenient use.
+ D3D11_TEXTURE2D_DESC backBufferDesc = {0};
+ backBuffer->GetDesc(&backBufferDesc);
+ m_renderTargetSize.Width = static_cast<float>(backBufferDesc.Width);
+ m_renderTargetSize.Height = static_cast<float>(backBufferDesc.Height);
+
+ // Create a descriptor for the depth/stencil buffer.
+ CD3D11_TEXTURE2D_DESC depthStencilDesc(
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ backBufferDesc.Width,
+ backBufferDesc.Height,
+ 1,
+ 1,
+ D3D11_BIND_DEPTH_STENCIL
+ );
+
+ // Allocate a 2-D surface as the depth/stencil buffer.
+ ComPtr<ID3D11Texture2D> depthStencil;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateTexture2D(
+ &depthStencilDesc,
+ nullptr,
+ &depthStencil
+ )
+ );
+
+ // Create a DepthStencil view on this surface to use on bind.
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDepthStencilView(
+ depthStencil.Get(),
+ &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
+ &m_depthStencilView
+ )
+ );
+
+ // Create a viewport descriptor of the full window size.
+ CD3D11_VIEWPORT viewport(
+ 0.0f,
+ 0.0f,
+ static_cast<float>(backBufferDesc.Width),
+ static_cast<float>(backBufferDesc.Height)
+ );
+
+ // Set the current viewport using the descriptor.
+ m_d3dContext->RSSetViewports(1, &viewport);
+
+ // Now we set up the Direct2D render target bitmap linked to the swapchain.
+ // Whenever we render to this bitmap, it will be directly rendered to the
+ // swapchain associated with the window.
+ D2D1_BITMAP_PROPERTIES1 bitmapProperties =
+ BitmapProperties1(
+ D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
+ PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
+ m_dpi,
+ m_dpi
+ );
+
+ // Direct2D needs the dxgi version of the backbuffer surface pointer.
+ ComPtr<IDXGISurface> dxgiBackBuffer;
+ DX::ThrowIfFailed(
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
+ );
+
+ // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
+ DX::ThrowIfFailed(
+ m_d2dContext->CreateBitmapFromDxgiSurface(
+ dxgiBackBuffer.Get(),
+ &bitmapProperties,
+ &m_d2dTargetBitmap
+ )
+ );
+
+ // So now we can set the Direct2D render target.
+ m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
+
+ // Set D2D text anti-alias mode to Grayscale to ensure proper rendering of text on intermediate surfaces.
+ m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
+
+
+ // Randomly generate some non-interactive asteroids to fit the screen.
+
+ m_asteroidData.clear();
+ for (int i = 0; i < SampleSettings::NumAsteroids; i++)
+ {
+ AsteroidData data;
+ data.pos.x = RandFloat(0.0f, m_windowBounds.Width);
+ data.pos.y = RandFloat(0.0f, m_windowBounds.Height);
+ float tempRot = RandFloat(static_cast<float>(-M_PI), static_cast<float>(M_PI));
+ float tempMag = RandFloat(0.0f, 17.0f);
+ data.vel.x = tempMag * cosf(tempRot);
+ data.vel.y = tempMag * sinf(tempRot);
+ data.rot = RandFloat(static_cast<float>(-M_PI), static_cast<float>(M_PI));
+ data.scale = RandFloat(0.1f, 1.0f);
+ data.rotVel = RandFloat(static_cast<float>(-M_PI), static_cast<float>(M_PI)) / (7.0f + 3.0f * data.scale);
+ m_asteroidData.push_back(data);
+ }
+
+
+ if (m_particleData.size() == 0)
+ {
+ // Initialize the interactive particle buffer to fill the window if it is empty.
+
+ for (int i = 0; i < SampleSettings::Performance::ParticleCountMax; i++)
+ {
+ ParticleData data;
+ data.pos.x = RandFloat(0.0f, m_windowBounds.Width);
+ data.pos.y = RandFloat(0.0f, m_windowBounds.Height);
+ data.vel = float2(0.0f, 0.0f);
+ m_particleData.push_back(data);
+ }
+ }
+ else
+ {
+ // Otherwise, move the interactive particles to fit within the screen.
+
+ for (auto particle = m_particleData.begin(); particle != m_particleData.end(); particle++)
+ {
+ if (particle->pos.x > m_windowBounds.Width)
+ {
+ particle->pos.x = m_windowBounds.Width;
+ }
+ if (particle->pos.y > m_windowBounds.Height)
+ {
+ particle->pos.y = m_windowBounds.Height;
+ }
+ }
+ }
+
+ m_sampleOverlay->UpdateForWindowSizeChange();
+}
+
+void SimpleSprites::Update(float timeTotal, float timeDelta)
+{
+ // Update the performance throttler.
+
+ auto control = m_autoThrottle->Update(timeDelta);
+
+ if (control == FrameWorkload::Increase)
+ {
+ m_numParticlesToDraw += SampleSettings::Performance::ParticleCountDelta;
+ }
+ if (control == FrameWorkload::Decrease)
+ {
+ m_numParticlesToDraw -= SampleSettings::Performance::ParticleCountDelta;
+ }
+ if (control != FrameWorkload::Maintain)
+ {
+ m_numParticlesToDraw = max(SampleSettings::Performance::ParticleCountMin, min(SampleSettings::Performance::ParticleCountMax, m_numParticlesToDraw));
+ if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
+ {
+ m_numParticlesToDraw = min(static_cast<int>(Parameters::MaximumCapacityCompatible - SampleSettings::NumAsteroids - 1), m_numParticlesToDraw);
+ }
+ }
+
+ // Update the non-interactive asteroids.
+ // Their behavior is to drift across the window with a fixed translational and rotational
+ // velocity. Upon crossing a boundary outside the window, their position wraps.
+
+ for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
+ {
+ static const float border = 100.0f;
+ asteroid->pos = asteroid->pos + asteroid->vel * timeDelta;
+ if (asteroid->vel.x < 0)
+ {
+ if (asteroid->pos.x < -border)
+ {
+ asteroid->pos.x = m_windowBounds.Width + border;
+ }
+ }
+ else
+ {
+ if (asteroid->pos.x > m_windowBounds.Width + border)
+ {
+ asteroid->pos.x = -border;
+ }
+ }
+ if (asteroid->vel.y < 0)
+ {
+ if (asteroid->pos.y < -border)
+ {
+ asteroid->pos.y = m_windowBounds.Height + border;
+ }
+ }
+ else
+ {
+ if (asteroid->pos.y > m_windowBounds.Height + border)
+ {
+ asteroid->pos.y = -border;
+ }
+ }
+
+ asteroid->rot += asteroid->rotVel * timeDelta;
+ if (asteroid->rot > static_cast<float>(M_PI))
+ {
+ asteroid->rot -= 2.0f * static_cast<float>(M_PI);
+ }
+ if (asteroid->rot < static_cast<float>(-M_PI))
+ {
+ asteroid->rot += 2.0f * static_cast<float>(M_PI);
+ }
+ }
+
+ // Update the interactive particles.
+ // Their behavior is to be gravitationally attracted to two oscillating gravity
+ // wells and repelled by any pressed pointer points. Upon reaching the edge of
+ // the window, the particles bounce.
+
+ // Add two gravity wells that move throughout the window.
+ float2 wellPositions[] =
+ {
+ float2(
+ (1.0f + 0.8f * cosf(timeTotal / (2.0f * static_cast<float>(M_PI)) + 3.0f)) * m_windowBounds.Width / 2.0f,
+ (1.0f + 0.8f * sinf(timeTotal / 5.0f)) * m_windowBounds.Height / 2.0f
+ ),
+ float2(
+ (1.0f + 0.8f * cosf(timeTotal / static_cast<float>(M_PI * M_PI) + 1.0f)) * m_windowBounds.Width / 2.0f,
+ (1.0f + 0.8f * sinf(timeTotal / static_cast<float>(M_PI))) * m_windowBounds.Height / 2.0f
+ )
+ };
+
+ for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
+ {
+ if (particle->pos.x < 0)
+ {
+ particle->vel.x = abs(particle->vel.x);
+ }
+ if (particle->pos.x > m_windowBounds.Width)
+ {
+ particle->vel.x = -abs(particle->vel.x);
+ }
+ if (particle->pos.y < 0)
+ {
+ particle->vel.y = abs(particle->vel.y);
+ }
+ if (particle->pos.y > m_windowBounds.Height)
+ {
+ particle->vel.y = -abs(particle->vel.y);
+ }
+
+ for (auto repulsor = m_repulsors.begin(); repulsor != m_repulsors.end(); repulsor++)
+ {
+ float2 delta = particle->pos - repulsor->second;
+ float deltaLength = length(delta) + 24.0f; // Offset length to avoid division by zero.
+ float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
+ particle->vel = particle->vel + SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
+ }
+
+ for (int i = 0; i < ARRAYSIZE(wellPositions); i++)
+ {
+ float gravitySign = 1.0f;
+ if ((static_cast<int>(timeTotal / 2.0f) + 1) % 10 == 0)
+ {
+ // Every 20 seconds, "explode" the gravity wells for 2 seconds.
+ gravitySign = -1.0f;
+ }
+ float2 delta = wellPositions[i] - particle->pos;
+ float deltaLength = length(delta) + 24.0f;
+ float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
+ particle->vel = particle->vel + gravitySign * 0.2f * SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
+ }
+
+ particle->vel = particle->vel * (1.0f - SampleSettings::Physics::Damping);
+
+ // Add random noise to the velocity to prevent particles from locking together.
+
+ particle->vel.x += RandFloat(-0.5f, 0.5f);
+ particle->vel.y += RandFloat(-0.5f, 0.5f);
+
+ particle->pos = particle->pos + particle->vel * timeDelta;
+ }
+}
+
+void SimpleSprites::Render()
+{
+ m_d3dContext->OMSetRenderTargets(
+ 1,
+ m_renderTargetView.GetAddressOf(),
+ nullptr
+ );
+
+ m_d3dContext->ClearRenderTargetView(
+ m_renderTargetView.Get(),
+ reinterpret_cast<float*>(&D2D1::ColorF(D2D1::ColorF::MidnightBlue))
+ );
+
+ m_spriteBatch->Begin();
+
+ // Draw the background.
+
+ m_spriteBatch->Draw(
+ m_background.Get(),
+ float2(0.5f, 0.5f),
+ PositionUnits::Normalized,
+ float2(1.0f, 1.0f),
+ SizeUnits::Normalized
+ );
+
+ // Draw the non-interactive asteroids.
+
+ for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
+ {
+ m_spriteBatch->Draw(
+ m_asteroid.Get(),
+ asteroid->pos,
+ PositionUnits::DIPs,
+ float2(1.0f, 1.0f) * asteroid->scale,
+ SizeUnits::Normalized,
+ float4(0.8f, 0.8f, 1.0f, 1.0f),
+ asteroid->rot
+ );
+ }
+
+ // Draw the interactive particles.
+
+ for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
+ {
+ float alpha = length(particle->vel) / 200.0f;
+ m_spriteBatch->Draw(
+ m_particle.Get(),
+ particle->pos,
+ PositionUnits::DIPs,
+ float2(32.0f, 32.0f),
+ SizeUnits::DIPs,
+ float4(0.1f, 0.02f, 0.0f, alpha),
+ 0.0f,
+ BlendMode::Additive
+ );
+ }
+
+ m_spriteBatch->End();
+
+ // Render the Sample Overlay.
+
+ m_sampleOverlay->Render();
+}
+
+float SimpleSprites::RandFloat(float min, float max)
+{
+ return (static_cast<float>(rand() % RAND_MAX) / static_cast<float>(RAND_MAX)) * (max - min) + min;
+}
+
+void SimpleSprites::AddRepulsor(_In_ uint32 id, _In_ float2 position)
+{
+ m_repulsors[id] = position;
+}
+
+void SimpleSprites::MoveRepulsor(_In_ uint32 id, _In_ float2 position)
+{
+ m_repulsors[id] = position;
+}
+
+void SimpleSprites::RemoveRepulsor(_In_ uint32 id)
+{
+ m_repulsors.erase(id);
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#include "DirectXBase.h"
+#include "SampleOverlay.h"
+#include "AutoThrottle.h"
+#include "BasicSprites.h"
+
+namespace SampleSettings
+{
+ static const unsigned int NumAsteroids = 50;
+ namespace Performance
+ {
+ static const float TargetFrameTime = 1.0f / 20.0f;
+ static const unsigned int InitialParticleCount = 5000;
+ static const unsigned int ParticleCountDelta = 32;
+ static const unsigned int ParticleCountMin = 1000;
+ static const unsigned int ParticleCountMax = 60000;
+ }
+ namespace Physics
+ {
+ static const float Gravity = 40000000.0f;
+ static const float Damping = 0.015f;
+ }
+}
+
+struct AsteroidData
+{
+ float2 pos;
+ float2 vel;
+ float rot;
+ float rotVel;
+ float scale;
+};
+
+struct ParticleData
+{
+ float2 pos;
+ float2 vel;
+};
+
+ref class SimpleSprites : public DirectXBase
+{
+public:
+ SimpleSprites();
+ virtual void CreateDeviceIndependentResources() override;
+ virtual void CreateDeviceResources() override;
+ virtual void CreateWindowSizeDependentResources() override;
+ virtual void Render() override;
+ void Initialize(
+ _In_ Windows::UI::Core::CoreWindow^ window,
+ _In_ Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ swapChainPanel,
+ _In_ float dpi
+ ) new;
+ void Update(float timeTotal, float timeDelta);
+ void AddRepulsor(_In_ uint32 id, _In_ float2 position);
+ void MoveRepulsor(_In_ uint32 id, _In_ float2 position);
+ void RemoveRepulsor(_In_ uint32 id);
+
+private:
+ float RandFloat(float min, float max);
+ SampleOverlay^ m_sampleOverlay;
+ AutoThrottle^ m_autoThrottle;
+ BasicSprites::SpriteBatch^ m_spriteBatch;
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> m_background;
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> m_asteroid;
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> m_particle;
+ std::vector<AsteroidData> m_asteroidData;
+ std::vector<ParticleData> m_particleData;
+ std::map<uint32, float2> m_repulsors;
+ int m_numParticlesToDraw;
+ Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ panel_;
+};
//
#include "pch.h"
+
+#pragma comment(lib, "d2d1.lib")
+#pragma comment(lib, "d3d11.lib")
+#pragma comment(lib, "dxgi.lib")
+#pragma comment(lib, "dwrite.lib")
+#pragma comment(lib, "dxguid.lib")
+#pragma comment(lib, "xaudio2.lib")
+#pragma comment(lib, "xinput.lib")
+#pragma comment(lib, "windowscodecs.lib")
+
+
+//#pragma comment(lib, "")
+//#pragma comment(lib, "")
+//#pragma comment(lib, "")
+//#pragma comment(lib, "")
+
#pragma once
+#include <wrl.h>
+#include <d3d11_1.h>
+#include <d2d1_1.h>
+#include <d2d1effects.h>
+#include <dwrite_1.h>
+#include <wincodec.h>
+#include <DirectXMath.h>
+
+#include <xaudio2.h>
+#include <xaudio2fx.h>
+
+#include <mmreg.h>
+#include <mfidl.h>
+#include <mfapi.h>
+#include <mfreadwrite.h>
+
+#include <XInput.h>
+
+#include <stdio.h>
+#include <vector>
+#include <memory>
#include "App.xaml.h"