OSDN Git Service

最初のコミット
authorsfpgmr <sfpg@users.sourceforge.jp>
Sat, 21 Apr 2012 21:26:18 +0000 (06:26 +0900)
committersfpgmr <sfpg@users.sourceforge.jp>
Sat, 21 Apr 2012 21:26:18 +0000 (06:26 +0900)
43 files changed:
ShootingGame/App.xaml.cpp
ShootingGame/App.xaml.h
ShootingGame/AutoThrottle.cpp [new file with mode: 0644]
ShootingGame/AutoThrottle.h [new file with mode: 0644]
ShootingGame/BasicLoader.cpp [new file with mode: 0644]
ShootingGame/BasicLoader.h [new file with mode: 0644]
ShootingGame/BasicMath.h [new file with mode: 0644]
ShootingGame/BasicReaderWriter.cpp [new file with mode: 0644]
ShootingGame/BasicReaderWriter.h [new file with mode: 0644]
ShootingGame/BasicShapes.h [new file with mode: 0644]
ShootingGame/BasicSprites.GeometryShader.gs.hlsl [new file with mode: 0644]
ShootingGame/BasicSprites.GeometryShader.vs.hlsl [new file with mode: 0644]
ShootingGame/BasicSprites.Instancing.vs.hlsl [new file with mode: 0644]
ShootingGame/BasicSprites.Replication.vs.hlsl [new file with mode: 0644]
ShootingGame/BasicSprites.cpp [new file with mode: 0644]
ShootingGame/BasicSprites.h [new file with mode: 0644]
ShootingGame/BasicSprites.ps.hlsl [new file with mode: 0644]
ShootingGame/BasicTimer.cpp [new file with mode: 0644]
ShootingGame/BasicTimer.h [new file with mode: 0644]
ShootingGame/BlankPage.xaml [deleted file]
ShootingGame/DDSTextureLoader.cpp [new file with mode: 0644]
ShootingGame/DDSTextureLoader.h [new file with mode: 0644]
ShootingGame/DirectXBase.cpp [new file with mode: 0644]
ShootingGame/DirectXBase.h [new file with mode: 0644]
ShootingGame/DirectXSample.h [new file with mode: 0644]
ShootingGame/MainPage.xaml [new file with mode: 0644]
ShootingGame/MainPage.xaml.cpp [moved from ShootingGame/BlankPage.xaml.cpp with 83% similarity]
ShootingGame/MainPage.xaml.h [moved from ShootingGame/BlankPage.xaml.h with 69% similarity]
ShootingGame/SampleOverlay.cpp [new file with mode: 0644]
ShootingGame/SampleOverlay.h [new file with mode: 0644]
ShootingGame/ShootingGame.vcxproj
ShootingGame/SimpleSprites.cpp [new file with mode: 0644]
ShootingGame/SimpleSprites.h [new file with mode: 0644]
ShootingGame/ida.dds [new file with mode: 0644]
ShootingGame/m31.png [new file with mode: 0644]
ShootingGame/particle.dds [new file with mode: 0644]
ShootingGame/pch.cpp
ShootingGame/pch.h
ShootingGame/smallTile-sdk.png [new file with mode: 0644]
ShootingGame/splash-sdk.png [new file with mode: 0644]
ShootingGame/squareTile-sdk.png [new file with mode: 0644]
ShootingGame/storeLogo-sdk.png [new file with mode: 0644]
ShootingGame/windowsbig-sdk.png [new file with mode: 0644]

index 956c271..1a0242c 100644 (file)
@@ -4,13 +4,18 @@
 //
 
 #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;
@@ -21,6 +26,9 @@ using namespace Windows::UI::Xaml::Input;
 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
 
@@ -47,14 +55,48 @@ void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEvent
                //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>
@@ -68,3 +110,93 @@ void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
 {
        //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
+                       )
+                       );
+       }
+}
+
index b2857c9..0cd5235 100644 (file)
@@ -7,6 +7,8 @@
 
 #include "pch.h"
 #include "App.g.h"
+#include "SimpleSprites.h"
+#include "BasicTimer.h"
 
 namespace ShootingGame
 {
@@ -21,5 +23,52 @@ 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
+                       );
+
+
+
        };
 }
diff --git a/ShootingGame/AutoThrottle.cpp b/ShootingGame/AutoThrottle.cpp
new file mode 100644 (file)
index 0000000..8f97d45
--- /dev/null
@@ -0,0 +1,52 @@
+//// 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;
+}
diff --git a/ShootingGame/AutoThrottle.h b/ShootingGame/AutoThrottle.h
new file mode 100644 (file)
index 0000000..ce1dae2
--- /dev/null
@@ -0,0 +1,26 @@
+//// 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;
+};
diff --git a/ShootingGame/BasicLoader.cpp b/ShootingGame/BasicLoader.cpp
new file mode 100644 (file)
index 0000000..2134d13
--- /dev/null
@@ -0,0 +1,768 @@
+//// 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
+            );
+    }));
+}
diff --git a/ShootingGame/BasicLoader.h b/ShootingGame/BasicLoader.h
new file mode 100644 (file)
index 0000000..8465cdd
--- /dev/null
@@ -0,0 +1,174 @@
+//// 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
+        );
+};
diff --git a/ShootingGame/BasicMath.h b/ShootingGame/BasicMath.h
new file mode 100644 (file)
index 0000000..5c9c4c9
--- /dev/null
@@ -0,0 +1,511 @@
+//// 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;
+}
diff --git a/ShootingGame/BasicReaderWriter.cpp b/ShootingGame/BasicReaderWriter.cpp
new file mode 100644 (file)
index 0000000..e545dc0
--- /dev/null
@@ -0,0 +1,175 @@
+//// 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);
+    });
+}
diff --git a/ShootingGame/BasicReaderWriter.h b/ShootingGame/BasicReaderWriter.h
new file mode 100644 (file)
index 0000000..94dbaaa
--- /dev/null
@@ -0,0 +1,45 @@
+//// 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
+        );
+};
diff --git a/ShootingGame/BasicShapes.h b/ShootingGame/BasicShapes.h
new file mode 100644 (file)
index 0000000..e894616
--- /dev/null
@@ -0,0 +1,86 @@
+//// 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
+        );
+
+};
diff --git a/ShootingGame/BasicSprites.GeometryShader.gs.hlsl b/ShootingGame/BasicSprites.GeometryShader.gs.hlsl
new file mode 100644 (file)
index 0000000..27290f9
--- /dev/null
@@ -0,0 +1,68 @@
+// 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();
+}
diff --git a/ShootingGame/BasicSprites.GeometryShader.vs.hlsl b/ShootingGame/BasicSprites.GeometryShader.vs.hlsl
new file mode 100644 (file)
index 0000000..3ce1549
--- /dev/null
@@ -0,0 +1,35 @@
+// 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;
+}
diff --git a/ShootingGame/BasicSprites.Instancing.vs.hlsl b/ShootingGame/BasicSprites.Instancing.vs.hlsl
new file mode 100644 (file)
index 0000000..690b9f3
--- /dev/null
@@ -0,0 +1,51 @@
+// 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;
+}
diff --git a/ShootingGame/BasicSprites.Replication.vs.hlsl b/ShootingGame/BasicSprites.Replication.vs.hlsl
new file mode 100644 (file)
index 0000000..052f8d0
--- /dev/null
@@ -0,0 +1,32 @@
+// 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;
+}
diff --git a/ShootingGame/BasicSprites.cpp b/ShootingGame/BasicSprites.cpp
new file mode 100644 (file)
index 0000000..71f419c
--- /dev/null
@@ -0,0 +1,880 @@
+//// 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++;
+}
diff --git a/ShootingGame/BasicSprites.h b/ShootingGame/BasicSprites.h
new file mode 100644 (file)
index 0000000..ba87a8b
--- /dev/null
@@ -0,0 +1,176 @@
+//// 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;
+    };
+}
diff --git a/ShootingGame/BasicSprites.ps.hlsl b/ShootingGame/BasicSprites.ps.hlsl
new file mode 100644 (file)
index 0000000..e7da5dd
--- /dev/null
@@ -0,0 +1,24 @@
+//// 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);
+}
diff --git a/ShootingGame/BasicTimer.cpp b/ShootingGame/BasicTimer.cpp
new file mode 100644 (file)
index 0000000..65dc31d
--- /dev/null
@@ -0,0 +1,64 @@
+//// 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;
+}
diff --git a/ShootingGame/BasicTimer.h b/ShootingGame/BasicTimer.h
new file mode 100644 (file)
index 0000000..8cd8fda
--- /dev/null
@@ -0,0 +1,32 @@
+//// 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();
+    }
+};
diff --git a/ShootingGame/BlankPage.xaml b/ShootingGame/BlankPage.xaml
deleted file mode 100644 (file)
index 6c7866b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<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>
diff --git a/ShootingGame/DDSTextureLoader.cpp b/ShootingGame/DDSTextureLoader.cpp
new file mode 100644 (file)
index 0000000..b8ef9d8
--- /dev/null
@@ -0,0 +1,1129 @@
+//--------------------------------------------------------------------------------------
+// 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
+                        );
+}
diff --git a/ShootingGame/DDSTextureLoader.h b/ShootingGame/DDSTextureLoader.h
new file mode 100644 (file)
index 0000000..18a179b
--- /dev/null
@@ -0,0 +1,27 @@
+//--------------------------------------------------------------------------------------
+// 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
+    );
diff --git a/ShootingGame/DirectXBase.cpp b/ShootingGame/DirectXBase.cpp
new file mode 100644 (file)
index 0000000..9ff707a
--- /dev/null
@@ -0,0 +1,373 @@
+//// 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, &parameters);
+
+    // 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);
+    }
+}
diff --git a/ShootingGame/DirectXBase.h b/ShootingGame/DirectXBase.h
new file mode 100644 (file)
index 0000000..adfa737
--- /dev/null
@@ -0,0 +1,57 @@
+//// 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)
diff --git a/ShootingGame/DirectXSample.h b/ShootingGame/DirectXSample.h
new file mode 100644 (file)
index 0000000..c4b7f61
--- /dev/null
@@ -0,0 +1,21 @@
+//// 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);
+        }
+    }
+}
diff --git a/ShootingGame/MainPage.xaml b/ShootingGame/MainPage.xaml
new file mode 100644 (file)
index 0000000..a72b7a3
--- /dev/null
@@ -0,0 +1,11 @@
+<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>
similarity index 83%
rename from ShootingGame/BlankPage.xaml.cpp
rename to ShootingGame/MainPage.xaml.cpp
index 136e5fd..9c3a0f2 100644 (file)
@@ -1,10 +1,10 @@
 //
-//BlankPage.xaml.cpp
-//BlankPage.xaml クラスの実装。
+//MainPage.xaml.cpp
+//MainPage.xaml クラスの実装。
 //
 
 #include "pch.h"
-#include "BlankPage.xaml.h"
+#include "MainPage.xaml.h"
 
 using namespace ShootingGame;
 
@@ -21,7 +21,7 @@ using namespace Windows::UI::Xaml::Navigation;
 
 // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
 
-BlankPage::BlankPage()
+MainPage::MainPage()
 {
        InitializeComponent();
 }
@@ -31,6 +31,6 @@ BlankPage::BlankPage()
 /// </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)
 {
 }
similarity index 69%
rename from ShootingGame/BlankPage.xaml.h
rename to ShootingGame/MainPage.xaml.h
index ad6665f..6f74e1f 100644 (file)
@@ -1,22 +1,22 @@
 //
-//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;
diff --git a/ShootingGame/SampleOverlay.cpp b/ShootingGame/SampleOverlay.cpp
new file mode 100644 (file)
index 0000000..d60e2ba
--- /dev/null
@@ -0,0 +1,198 @@
+//// 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;
+}
diff --git a/ShootingGame/SampleOverlay.h b/ShootingGame/SampleOverlay.h
new file mode 100644 (file)
index 0000000..b71f7e0
--- /dev/null
@@ -0,0 +1,53 @@
+//// 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;
+};
index 89c0b10..6288e77 100644 (file)
     <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">
diff --git a/ShootingGame/SimpleSprites.cpp b/ShootingGame/SimpleSprites.cpp
new file mode 100644 (file)
index 0000000..d1f8959
--- /dev/null
@@ -0,0 +1,556 @@
+//// 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);
+}
diff --git a/ShootingGame/SimpleSprites.h b/ShootingGame/SimpleSprites.h
new file mode 100644 (file)
index 0000000..2b5fe91
--- /dev/null
@@ -0,0 +1,79 @@
+//// 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_;
+};
diff --git a/ShootingGame/ida.dds b/ShootingGame/ida.dds
new file mode 100644 (file)
index 0000000..a45f9a7
Binary files /dev/null and b/ShootingGame/ida.dds differ
diff --git a/ShootingGame/m31.png b/ShootingGame/m31.png
new file mode 100644 (file)
index 0000000..679a013
Binary files /dev/null and b/ShootingGame/m31.png differ
diff --git a/ShootingGame/particle.dds b/ShootingGame/particle.dds
new file mode 100644 (file)
index 0000000..ef34820
Binary files /dev/null and b/ShootingGame/particle.dds differ
index ef71c0c..6934890 100644 (file)
@@ -4,3 +4,19 @@
 //
 
 #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, "")
+
index 595c6df..89ef62e 100644 (file)
@@ -5,4 +5,25 @@
 
 #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"
diff --git a/ShootingGame/smallTile-sdk.png b/ShootingGame/smallTile-sdk.png
new file mode 100644 (file)
index 0000000..4790401
Binary files /dev/null and b/ShootingGame/smallTile-sdk.png differ
diff --git a/ShootingGame/splash-sdk.png b/ShootingGame/splash-sdk.png
new file mode 100644 (file)
index 0000000..30ac5b8
Binary files /dev/null and b/ShootingGame/splash-sdk.png differ
diff --git a/ShootingGame/squareTile-sdk.png b/ShootingGame/squareTile-sdk.png
new file mode 100644 (file)
index 0000000..81b9e32
Binary files /dev/null and b/ShootingGame/squareTile-sdk.png differ
diff --git a/ShootingGame/storeLogo-sdk.png b/ShootingGame/storeLogo-sdk.png
new file mode 100644 (file)
index 0000000..860d0be
Binary files /dev/null and b/ShootingGame/storeLogo-sdk.png differ
diff --git a/ShootingGame/windowsbig-sdk.png b/ShootingGame/windowsbig-sdk.png
new file mode 100644 (file)
index 0000000..05c15ff
Binary files /dev/null and b/ShootingGame/windowsbig-sdk.png differ