diff --git a/JGE/Dependencies/zlib/zlib.vcxproj.filters b/JGE/Dependencies/zlib/zlib.vcxproj.filters
new file mode 100644
index 000000000..cf2407be2
--- /dev/null
+++ b/JGE/Dependencies/zlib/zlib.vcxproj.filters
@@ -0,0 +1,60 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/JGE/JGE - win8.vcxproj b/JGE/JGE - win8.vcxproj
new file mode 100644
index 000000000..100c1a559
--- /dev/null
+++ b/JGE/JGE - win8.vcxproj
@@ -0,0 +1,365 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Profile
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {89159C26-2282-404A-A194-103B0A49DF7B}
+ JGE
+
+
+
+ StaticLibrary
+ false
+ MultiByte
+ v110
+ true
+
+
+ StaticLibrary
+ false
+ MultiByte
+ v110
+ true
+
+
+ StaticLibrary
+ false
+ MultiByte
+ v110
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ MinimumRecommendedRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+ JGE
+
+
+ JGE
+
+
+ JGE
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ src/zipFS;Dependencies/SDL/include;Dependencies/include;$(JGEEXTRAS);../Boost;../projects/mtg/include;include;%(AdditionalIncludeDirectories)
+ TIXML_USE_STL;WP8;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+ true
+
+
+ .\Release/JGE.pch
+ .\Release/
+ .\Release/
+ .\Release/
+ Level3
+ true
+ Default
+ true
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0c09
+
+
+ true
+ LIBCMT;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+ Disabled
+ src/zipFS;Dependencies/SDL/include;Dependencies/include;$(JGEEXTRAS);../Boost;../projects/mtg/include;include;%(AdditionalIncludeDirectories)
+ TIXML_USE_STL;WP8;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDLL
+
+
+ .\Debug/JGE.pch
+ .\Debug/
+ .\Debug/
+ .\Debug/
+ Level3
+ true
+ EditAndContinue
+ Default
+ true
+ true
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0c09
+
+
+ true
+
+
+
+
+ Full
+ OnlyExplicitInline
+ src/zipFS;Dependencies/SDL/include;Dependencies/include;$(JGEEXTRAS);../Boost;../projects/mtg/include;include;%(AdditionalIncludeDirectories)
+ TIXML_USE_STL;WP8;WIN32;NDEBUG;_LIB;_SECURE_SCL=0;_HAS_ITERATOR_DEBBUGING=0;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+ true
+
+
+ .\Release/JGE.pch
+ .\Release/
+ .\Release/
+ .\Release/
+ Level3
+ true
+ ProgramDatabase
+ Default
+ true
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0c09
+
+
+ true
+ LIBCMT;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ false
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JGE/src/DirectX/BasicLoader.cpp b/JGE/src/DirectX/BasicLoader.cpp
new file mode 100644
index 000000000..42a6297b7
--- /dev/null
+++ b/JGE/src/DirectX/BasicLoader.cpp
@@ -0,0 +1,672 @@
+//// 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
+#include
+#include
+#include
+#include
+#include
+#include "BasicLoader.h"
+#include "BasicShapes.h"
+#include
+
+using namespace Microsoft::WRL;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Foundation;
+using namespace Windows::ApplicationModel;
+using namespace std;
+using namespace concurrency;
+
+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
+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 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::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(meshData);
+
+ // The following 4 bytes define the number of indices in the mesh.
+ uint32 numIndices = *reinterpret_cast(meshData + sizeof(uint32));
+
+ // The next segment of the BasicMesh format contains the vertices of the mesh.
+ BasicVertex* vertices = reinterpret_cast(meshData + sizeof(uint32) * 2);
+
+ // The last segment of the BasicMesh format contains the indices of the mesh.
+ uint16* indices = reinterpret_cast(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;
+ CD3D11_BUFFER_DESC vertexBufferDesc(numVertices * sizeof(BasicVertex), D3D11_BIND_VERTEX_BUFFER);
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &vertexBufferDesc,
+ &vertexBufferData,
+ vertexBuffer
+ )
+ );
+
+ D3D11_SUBRESOURCE_DATA indexBufferData = {0};
+ indexBufferData.pSysMem = indices;
+ indexBufferData.SysMemPitch = 0;
+ indexBufferData.SysMemSlicePitch = 0;
+ CD3D11_BUFFER_DESC indexBufferDesc(numIndices * sizeof(uint16), D3D11_BIND_INDEX_BUFFER);
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &indexBufferDesc,
+ &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::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^ 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);
+ }
+}
+
+task 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
+ )
+{
+ // This method assumes that the lifetime of input arguments may be shorter
+ // than the duration of this task. In order to ensure accurate results, a
+ // copy of all arguments passed by pointer must be made. The method then
+ // ensures that the lifetime of the copied data exceeds that of the task.
+
+ // Create copies of the layoutDesc array as well as the SemanticName strings,
+ // both of which are pointers to data whose lifetimes may be shorter than that
+ // of this method's task.
+ shared_ptr> layoutDescCopy;
+ shared_ptr> layoutDescSemanticNamesCopy;
+ if (layoutDesc != nullptr)
+ {
+ layoutDescCopy.reset(
+ new vector(
+ layoutDesc,
+ layoutDesc + layoutDescNumElements
+ )
+ );
+
+ layoutDescSemanticNamesCopy.reset(
+ new vector(layoutDescNumElements)
+ );
+
+ for (uint32 i = 0; i < layoutDescNumElements; i++)
+ {
+ layoutDescSemanticNamesCopy->at(i).assign(layoutDesc[i].SemanticName);
+ }
+ }
+
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateVertexShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+
+ if (layout != nullptr)
+ {
+ if (layoutDesc != nullptr)
+ {
+ // Reassign the SemanticName elements of the layoutDesc array copy to point
+ // to the corresponding copied strings. Performing the assignment inside the
+ // lambda body ensures that the lambda will take a reference to the shared_ptr
+ // that holds the data. This will guarantee that the data is still valid when
+ // CreateInputLayout is called.
+ for (uint32 i = 0; i < layoutDescNumElements; i++)
+ {
+ layoutDescCopy->at(i).SemanticName = layoutDescSemanticNamesCopy->at(i).c_str();
+ }
+ }
+
+ CreateInputLayout(
+ bytecode->Data,
+ bytecode->Length,
+ layoutDesc == nullptr ? nullptr : layoutDescCopy->data(),
+ layoutDescNumElements,
+ layout
+ );
+
+ SetDebugName(*layout, filename);
+ }
+ });
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ )
+{
+ Platform::Array^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreatePixelShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ 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^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateComputeShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ 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^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ 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^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShaderWithStreamOutput(
+ bytecode->Data,
+ bytecode->Length,
+ streamOutDeclaration,
+ numEntries,
+ bufferStrides,
+ numStrides,
+ rasterizedStream,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task 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
+ )
+{
+ // This method assumes that the lifetime of input arguments may be shorter
+ // than the duration of this task. In order to ensure accurate results, a
+ // copy of all arguments passed by pointer must be made. The method then
+ // ensures that the lifetime of the copied data exceeds that of the task.
+
+ // Create copies of the streamOutDeclaration array as well as the SemanticName
+ // strings, both of which are pointers to data whose lifetimes may be shorter
+ // than that of this method's task.
+ shared_ptr> streamOutDeclarationCopy;
+ shared_ptr> streamOutDeclarationSemanticNamesCopy;
+ if (streamOutDeclaration != nullptr)
+ {
+ streamOutDeclarationCopy.reset(
+ new vector(
+ streamOutDeclaration,
+ streamOutDeclaration + numEntries
+ )
+ );
+
+ streamOutDeclarationSemanticNamesCopy.reset(
+ new vector(numEntries)
+ );
+
+ for (uint32 i = 0; i < numEntries; i++)
+ {
+ streamOutDeclarationSemanticNamesCopy->at(i).assign(streamOutDeclaration[i].SemanticName);
+ }
+ }
+
+ // Create a copy of the bufferStrides array, which is a pointer to data
+ // whose lifetime may be shorter than that of this method's task.
+ shared_ptr> bufferStridesCopy;
+ if (bufferStrides != nullptr)
+ {
+ bufferStridesCopy.reset(
+ new vector(
+ bufferStrides,
+ bufferStrides + numStrides
+ )
+ );
+ }
+
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ if (streamOutDeclaration != nullptr)
+ {
+ // Reassign the SemanticName elements of the streamOutDeclaration array copy to
+ // point to the corresponding copied strings. Performing the assignment inside the
+ // lambda body ensures that the lambda will take a reference to the shared_ptr
+ // that holds the data. This will guarantee that the data is still valid when
+ // CreateGeometryShaderWithStreamOutput is called.
+ for (uint32 i = 0; i < numEntries; i++)
+ {
+ streamOutDeclarationCopy->at(i).SemanticName = streamOutDeclarationSemanticNamesCopy->at(i).c_str();
+ }
+ }
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateGeometryShaderWithStreamOutput(
+ bytecode->Data,
+ bytecode->Length,
+ streamOutDeclaration == nullptr ? nullptr : streamOutDeclarationCopy->data(),
+ numEntries,
+ bufferStrides == nullptr ? nullptr : bufferStridesCopy->data(),
+ numStrides,
+ rasterizedStream,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+ });
+}
+
+void BasicLoader::LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ )
+{
+ Platform::Array^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateHullShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ 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^ bytecode = m_basicReaderWriter->ReadData(filename);
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDomainShader(
+ bytecode->Data,
+ bytecode->Length,
+ nullptr,
+ shader
+ )
+ );
+
+ SetDebugName(*shader, filename);
+}
+
+task BasicLoader::LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ bytecode)
+ {
+ 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^ meshData = m_basicReaderWriter->ReadData(filename);
+
+ CreateMesh(
+ meshData->Data,
+ vertexBuffer,
+ indexBuffer,
+ vertexCount,
+ indexCount,
+ filename
+ );
+}
+
+task BasicLoader::LoadMeshAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ )
+{
+ return m_basicReaderWriter->ReadDataAsync(filename).then([=](const Platform::Array^ meshData)
+ {
+ CreateMesh(
+ meshData->Data,
+ vertexBuffer,
+ indexBuffer,
+ vertexCount,
+ indexCount,
+ filename
+ );
+ });
+}
diff --git a/JGE/src/DirectX/BasicLoader.h b/JGE/src/DirectX/BasicLoader.h
new file mode 100644
index 000000000..2eac19aee
--- /dev/null
+++ b/JGE/src/DirectX/BasicLoader.h
@@ -0,0 +1,155 @@
+//// 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"
+
+// A simple loader class that provides support for loading shaders, textures,
+// and meshes from files on disk. Provides synchronous and asynchronous methods.
+ref class BasicLoader
+{
+internal:
+ BasicLoader(
+ _In_ ID3D11Device* d3dDevice
+// ,_In_opt_ IWICImagingFactory2* wicFactory = nullptr
+ );
+
+ 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
+ );
+
+ concurrency::task 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
+ );
+
+ concurrency::task LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11PixelShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ );
+
+ concurrency::task LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11ComputeShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11GeometryShader** shader
+ );
+
+ concurrency::task 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
+ );
+
+ concurrency::task 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
+ );
+
+ concurrency::task LoadShaderAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11HullShader** shader
+ );
+
+ void LoadShader(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11DomainShader** shader
+ );
+
+ concurrency::task 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
+ );
+
+ concurrency::task LoadMeshAsync(
+ _In_ Platform::String^ filename,
+ _Out_ ID3D11Buffer** vertexBuffer,
+ _Out_ ID3D11Buffer** indexBuffer,
+ _Out_opt_ uint32* vertexCount,
+ _Out_opt_ uint32* indexCount
+ );
+
+private:
+ Microsoft::WRL::ComPtr m_d3dDevice;
+// Microsoft::WRL::ComPtr m_wicFactory;
+ BasicReaderWriter^ m_basicReaderWriter;
+
+ template
+ inline void SetDebugName(
+ _In_ DeviceChildType* object,
+ _In_ Platform::String^ name
+ );
+
+ Platform::String^ GetExtension(
+ _In_ Platform::String^ filename
+ );
+
+ 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/JGE/src/DirectX/BasicMath.h b/JGE/src/DirectX/BasicMath.h
new file mode 100644
index 000000000..8424c8622
--- /dev/null
+++ b/JGE/src/DirectX/BasicMath.h
@@ -0,0 +1,531 @@
+//// 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
+
+// This header defines helper utilities to make DirectX APIs work with exceptions.
+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);
+ }
+ }
+}
+
+#define _USE_MATH_DEFINES
+#include
+
+// This header defines math and matrix helper functions and structures used
+// by DirectX SDK samples.
+
+// Common Constants
+
+#define PI_F 3.1415927f
+
+// Template Vector & Matrix Classes
+
+template 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(this)[index];
+ }
+
+ Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { }
+};
+
+template 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(this)[index];
+ }
+
+ Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { }
+};
+
+template 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(this)[index];
+ }
+
+ Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { }
+};
+
+template 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(this)[index*4]);
+ }
+};
+
+// Template Vector Operations
+
+template
+T dot(Vector2 a, Vector2 b)
+{
+ return a.x * b.x + a.y * b.y;
+}
+
+template
+T dot(Vector3 a, Vector3 b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+template
+T dot(Vector4 a, Vector4 b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z + a.w + b.w;
+}
+
+template
+T length(Vector2 a)
+{
+ return sqrt(a.x * a.x + a.y * a.y);
+}
+
+template
+T length(Vector3 a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
+}
+
+template
+T length(Vector4 a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w);
+}
+
+template
+Vector3 cross(Vector3 a, Vector3 b)
+{
+ return Vector3((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
+Vector2 normalize(Vector2 a)
+{
+ T len = length(a);
+ return Vector2(a.x / len, a.y / len);
+}
+
+template
+Vector3 normalize(Vector3 a)
+{
+ T len = length(a);
+ return Vector3(a.x / len, a.y / len, a.z / len);
+}
+
+template
+Vector4 normalize(Vector4 a)
+{
+ T len = length(a);
+ return Vector4(a.x / len, a.y / len, a.z / len, a.w / len);
+}
+
+// Template Vector Operators
+
+template
+Vector2 operator-(Vector2 a, Vector2 b)
+{
+ return Vector2(a.x - b.x, a.y - b.y);
+}
+
+template
+Vector2 operator-(Vector2 a)
+{
+ return Vector2(-a.x, -a.y);
+}
+
+template
+Vector3 operator-(Vector3 a, Vector3 b)
+{
+ return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+template
+Vector3 operator-(Vector3 a)
+{
+ return Vector3(-a.x, -a.y, -a.z);
+}
+
+template
+Vector4 operator-(Vector4 a, Vector4 b)
+{
+ return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
+
+template
+Vector4 operator-(Vector4 a)
+{
+ return Vector4(-a.x, -a.y, -a.z, -a.w);
+}
+
+template
+Vector2 operator+(Vector2 a, Vector2 b)
+{
+ return Vector2(a.x + b.x, a.y + b.y);
+}
+
+template
+Vector3 operator+(Vector3 a, Vector3 b)
+{
+ return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+template
+Vector4 operator+(Vector4 a, Vector4 b)
+{
+ return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
+
+template
+Vector2 operator*(Vector2 a, T s)
+{
+ return Vector2(a.x * s, a.y * s);
+}
+
+template
+Vector2 operator*(T s, Vector2 a)
+{
+ return a * s;
+}
+
+template
+Vector2 operator*(Vector2 a, Vector2 b)
+{
+ return Vector2(a.x * b.x, a.y * b.y);
+}
+
+template
+Vector2 operator/(Vector2 a, T s)
+{
+ return Vector2(a.x / s, a.y / s);
+}
+
+template
+Vector3 operator*(Vector3 a, T s)
+{
+ return Vector3(a.x * s, a.y * s, a.z * s);
+}
+
+template
+Vector3 operator*(T s, Vector3 a)
+{
+ return a * s;
+}
+
+template
+Vector3 operator*(Vector3 a, Vector3 b)
+{
+ return Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
+}
+
+template
+Vector3 operator/(Vector3 a, T s)
+{
+ return Vector3(a.x / s, a.y / s, a.z / s);
+}
+
+template
+Vector4 operator*(Vector4 a, T s)
+{
+ return Vector4(a.x * s, a.y * s, a.z * s, a.w * s);
+}
+
+template
+Vector4 operator*(T s, Vector4 a)
+{
+ return a * s;
+}
+
+template
+Vector4 operator*(Vector4 a, Vector4 b)
+{
+ return Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+}
+
+template
+Vector4 operator/(Vector4 a, T s)
+{
+ return Vector4(a.x / s, a.y / s, a.z / s, a.w / s);
+}
+
+
+
+// Template Matrix Operations
+
+template
+Matrix4x4 transpose(Matrix4x4 m)
+{
+ return Matrix4x4(
+ 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
+Matrix4x4 mul(Matrix4x4 m1, Matrix4x4 m2)
+{
+ Matrix4x4 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 float2;
+typedef Vector3 float3;
+typedef Vector4 float4;
+
+typedef Matrix4x4 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 * (PI_F / 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 * (PI_F / 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 * (PI_F / 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 * (PI_F / 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/JGE/src/DirectX/BasicReaderWriter.cpp b/JGE/src/DirectX/BasicReaderWriter.cpp
new file mode 100644
index 000000000..a6f8cfbc2
--- /dev/null
+++ b/JGE/src/DirectX/BasicReaderWriter.cpp
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+#include "BasicReaderWriter.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^ 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,
+ FILE_SHARE_READ,
+ 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^ fileData = ref new Platform::Array(fileInfo.EndOfFile.LowPart);
+
+ if (!ReadFile(
+ file.Get(),
+ fileData->Data,
+ fileData->Length,
+ nullptr,
+ nullptr
+ ))
+ {
+ throw ref new Platform::FailureException();
+ }
+
+ return fileData;
+}
+
+task^> BasicReaderWriter::ReadDataAsync(
+ _In_ Platform::String^ filename
+ )
+{
+ return task(m_location->GetFileAsync(filename)).then([=](StorageFile^ file)
+ {
+ return FileIO::ReadBufferAsync(file);
+ }).then([=](IBuffer^ buffer)
+ {
+ auto fileData = ref new Platform::Array(buffer->Length);
+ DataReader::FromBuffer(buffer)->ReadBytes(fileData);
+ return fileData;
+ });
+}
+
+uint32 BasicReaderWriter::WriteData(
+ _In_ Platform::String^ filename,
+ _In_ const Platform::Array^ 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;
+}
+
+task BasicReaderWriter::WriteDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ const Platform::Array^ fileData
+ )
+{
+ return task(m_location->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([=](StorageFile^ file)
+ {
+ FileIO::WriteBytesAsync(file, fileData);
+ });
+}
diff --git a/JGE/src/DirectX/BasicReaderWriter.h b/JGE/src/DirectX/BasicReaderWriter.h
new file mode 100644
index 000000000..8cf54183f
--- /dev/null
+++ b/JGE/src/DirectX/BasicReaderWriter.h
@@ -0,0 +1,43 @@
+//// 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
+
+// A simple reader/writer class that provides support for reading and writing
+// files on disk. Provides synchronous and asynchronous methods.
+ref class BasicReaderWriter
+{
+private:
+ Windows::Storage::StorageFolder^ m_location;
+ Platform::String^ m_locationPath;
+
+internal:
+ BasicReaderWriter();
+ BasicReaderWriter(
+ _In_ Windows::Storage::StorageFolder^ folder
+ );
+
+ Platform::Array^ ReadData(
+ _In_ Platform::String^ filename
+ );
+
+ concurrency::task^> ReadDataAsync(
+ _In_ Platform::String^ filename
+ );
+
+ uint32 WriteData(
+ _In_ Platform::String^ filename,
+ _In_ const Platform::Array^ fileData
+ );
+
+ concurrency::task WriteDataAsync(
+ _In_ Platform::String^ filename,
+ _In_ const Platform::Array^ fileData
+ );
+};
diff --git a/JGE/src/DirectX/BasicShapes.h b/JGE/src/DirectX/BasicShapes.h
new file mode 100644
index 000000000..3abeab18e
--- /dev/null
+++ b/JGE/src/DirectX/BasicShapes.h
@@ -0,0 +1,88 @@
+//// 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"
+
+// Defines 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
+};
+
+// Defines 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
+};
+
+// A helper class that provides convenient functions for creating common
+// geometrical shapes used by DirectX SDK samples.
+ref class BasicShapes
+{
+internal:
+ 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 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/JGE/src/DirectX/BasicSprites.GeometryShader.gs.hlsl b/JGE/src/DirectX/BasicSprites.GeometryShader.gs.hlsl
new file mode 100644
index 000000000..aeb36812a
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.GeometryShader.gs.hlsl
@@ -0,0 +1,95 @@
+// 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;
+};
+
+cbuffer MvpMatrixCB
+{
+ float4x4 mvpMatrix;
+};
+
+struct GeometryShaderInput
+{
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 textRect : TRANSFORM3;
+ vector colors : COLOR0;
+ float4 pt_x: TRANSFORM4;
+ float4 pt_y: TRANSFORM5;
+};
+
+struct PixelShaderInput
+{
+ float4 pos : SV_POSITION;
+ float2 tex : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+
+void rotate(float4x4 matrixxx, float angle, float3 origin)
+{
+
+}
+
+// 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 spriteStream)
+{
+ float sinRotation;
+ float cosRotation;
+ sincos(input[0].rotation, sinRotation, cosRotation);
+
+ float2 texCoord[4];
+
+ texCoord[0] = float2(input[0].textRect[0], input[0].textRect[2]);
+ texCoord[1] = float2(input[0].textRect[1], input[0].textRect[2]);
+ texCoord[2] = float2(input[0].textRect[0], input[0].textRect[3]);
+ texCoord[3] = float2(input[0].textRect[1], input[0].textRect[3]);
+
+ float2 posDelta[4];
+
+ posDelta[0] = float2(0.0f, 0.0f);
+ posDelta[1] = float2( 2*input[0].offset.x, 0.0f);
+ posDelta[2] = float2(0.0f, -2*input[0].offset.y);
+ posDelta[3] = float2( 2*input[0].offset.x, -2*input[0].offset.y);
+ /*
+ 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++)
+ {
+ float4 colorFloat;
+ colorFloat[3] = (float)((input[0].colors[i] & 0xFF000000) >> 24) / (float)255;
+ colorFloat[0] = (float)((input[0].colors[i] & 0x00FF0000) >> 16) / (float)255;
+ colorFloat[1] = (float)((input[0].colors[i] & 0x0000FF00) >> 8) / (float)255;
+ colorFloat[2] = (float)((input[0].colors[i] & 0x000000FF) ) / (float)255;
+
+ 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 = colorFloat;
+ spriteStream.Append(streamElement);
+ }
+ spriteStream.RestartStrip();
+}
diff --git a/JGE/src/DirectX/BasicSprites.GeometryShader.vs.hlsl b/JGE/src/DirectX/BasicSprites.GeometryShader.vs.hlsl
new file mode 100644
index 000000000..d3ddb9f6a
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.GeometryShader.vs.hlsl
@@ -0,0 +1,44 @@
+// 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 textRect : TRANSFORM3;
+ vector colors : COLOR0;
+ float4 pt_x: TRANSFORM4;
+ float4 pt_y: TRANSFORM5;
+};
+
+struct GeometryShaderInput
+{
+ float2 origin : TRANSFORM0;
+ float2 offset : TRANSFORM1;
+ float rotation : TRANSFORM2;
+ float4 textRect : TRANSFORM3;
+ vector colors : COLOR0;
+ float4 pt_x: TRANSFORM4;
+ float4 pt_y: TRANSFORM5;
+};
+
+// 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.textRect = input.textRect;
+ ret.colors = input.colors;
+ ret.pt_x = input.pt_x;
+ ret.pt_y = input.pt_y;
+ return ret;
+}
diff --git a/JGE/src/DirectX/BasicSprites.Instancing.vs.hlsl b/JGE/src/DirectX/BasicSprites.Instancing.vs.hlsl
new file mode 100644
index 000000000..690b9f357
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.Instancing.vs.hlsl
@@ -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/JGE/src/DirectX/BasicSprites.Replication.vs.hlsl b/JGE/src/DirectX/BasicSprites.Replication.vs.hlsl
new file mode 100644
index 000000000..052f8d0ff
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.Replication.vs.hlsl
@@ -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/JGE/src/DirectX/BasicSprites.cpp b/JGE/src/DirectX/BasicSprites.cpp
new file mode 100644
index 000000000..34f686fa8
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.cpp
@@ -0,0 +1,988 @@
+//// 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
+
+// Warning: SpriteBatch performance is significantly decreased in
+// the Debug configuration. Release configuration is recommended
+// for accurate performance assessment.
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "BasicSprites.h"
+#include "BasicLoader.h"
+
+using namespace Microsoft::WRL;
+using namespace BasicSprites;
+
+SpriteBatch::SpriteBatch() :
+ m_capacity(0)
+{
+}
+
+void SpriteBatch::Initialize(
+ _In_ ID3D11Device1* d3dDevice,
+ _In_ int capacity
+ )
+{
+ 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(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 },
+ { "TRANSFORM", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_UINT, 0, 36, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 4, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 52, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "TRANSFORM", 5, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 68, 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.
+
+ CD3D11_BUFFER_DESC instanceDataBufferDesc(
+ m_capacity * sizeof(InstanceData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &instanceDataBufferDesc,
+ 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;
+
+ CD3D11_BUFFER_DESC vertexBufferDesc(
+ sizeof(vertexBufferData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &vertexBufferDesc,
+ &vertexInitialData,
+ &m_vertexBuffer
+ )
+ );
+
+ // Create the instance data buffer.
+
+ CD3D11_BUFFER_DESC instanceDataBufferDesc(
+ m_capacity * sizeof(InstanceData),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &instanceDataBufferDesc,
+ 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;
+
+ CD3D11_BUFFER_DESC indexBufferDesc(
+ sizeof(indexBufferData),
+ D3D11_BIND_INDEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &indexBufferDesc,
+ &indexInitialData,
+ &m_indexBuffer
+ )
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ // Create the vertex buffer.
+
+ CD3D11_BUFFER_DESC vertexBufferDesc(
+ m_capacity * 4 * sizeof(ReplicationVertex),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &vertexBufferDesc,
+ nullptr,
+ &m_vertexBuffer
+ )
+ );
+
+ m_vertexData.reset(new ReplicationVertex[m_capacity * 4]);
+
+ // Create the index buffer.
+
+ std::unique_ptr 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;
+
+ CD3D11_BUFFER_DESC indexBufferDesc(
+ m_capacity * 6 * sizeof(unsigned short),
+ D3D11_BIND_INDEX_BUFFER,
+ D3D11_USAGE_DEFAULT,
+ 0
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &indexBufferDesc,
+ &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.
+
+ CD3D11_BUFFER_DESC renderTargetInfoCbufferDesc(
+ 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
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &renderTargetInfoCbufferDesc,
+ nullptr,
+ &m_renderTargetInfoCbuffer
+ )
+ );
+
+ CD3D11_BUFFER_DESC mvpMatrixCbufferDesc(
+ 128, // Matrix4x4 float data.
+ D3D11_BIND_CONSTANT_BUFFER,
+ D3D11_USAGE_DYNAMIC,
+ D3D11_CPU_ACCESS_WRITE
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateBuffer(
+ &mvpMatrixCbufferDesc,
+ nullptr,
+ &m_mvpMatrixCbuffer
+ )
+ );
+
+ }
+}
+
+void SpriteBatch::AddTexture(
+ _In_ ID3D11Texture2D* texture
+ )
+{
+ TextureMapElement mapElement;
+ CD3D11_SHADER_RESOURCE_VIEW_DESC mapElementSrvDesc(
+ texture,
+ D3D11_SRV_DIMENSION_TEXTURE2D
+ );
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateShaderResourceView(
+ texture,
+ &mapElementSrvDesc,
+ &mapElement.srv
+ )
+ );
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture->GetDesc(&textureDesc);
+ mapElement.size = float2(
+ static_cast(textureDesc.Width),
+ static_cast(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 renderTargetView;
+ m_d3dContext->OMGetRenderTargets(
+ 1,
+ &renderTargetView,
+ nullptr
+ );
+
+ ComPtr renderTarget;
+ renderTargetView->GetResource(&renderTarget);
+
+ ComPtr renderTargetTexture;
+ renderTarget.As(&renderTargetTexture);
+
+ D3D11_TEXTURE2D_DESC renderTargetTextureDesc;
+ renderTargetTexture->GetDesc(&renderTargetTextureDesc);
+
+ m_renderTargetSize = float2(
+ static_cast(renderTargetTextureDesc.Width),
+ static_cast(renderTargetTextureDesc.Height)
+ );
+
+ m_mvpMatrix = identity();
+
+ 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)
+ {
+ CD3D11_BOX instanceDataBox(
+ 0,
+ 0,
+ 0,
+ sizeof(InstanceData) * m_numSpritesDrawn,
+ 1,
+ 1
+ );
+
+ m_d3dContext->UpdateSubresource(
+ m_instanceDataBuffer.Get(),
+ 0,
+ &instanceDataBox,
+ m_instanceData.get(),
+ 0,
+ 0
+ );
+ }
+ else if (m_technique == RenderTechnique::Replication)
+ {
+ CD3D11_BOX vertexDataBox(
+ 0,
+ 0,
+ 0,
+ sizeof(ReplicationVertex) * m_numSpritesDrawn * 4,
+ 1,
+ 1
+ );
+
+ m_d3dContext->UpdateSubresource(
+ m_vertexBuffer.Get(),
+ 0,
+ &vertexDataBox,
+ 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(mappedSubresource.pData) = m_renderTargetSize;
+ m_d3dContext->Unmap(
+ m_renderTargetInfoCbuffer.Get(),
+ 0
+ );
+
+ m_d3dContext->Map(
+ m_mvpMatrixCbuffer.Get(),
+ 0,
+ D3D11_MAP_WRITE_DISCARD,
+ 0,
+ &mappedSubresource
+ );
+ *static_cast(mappedSubresource.pData) = m_mvpMatrix;
+ m_d3dContext->Unmap(
+ m_mvpMatrixCbuffer.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()
+ );
+
+ m_d3dContext->GSSetConstantBuffers(
+ 1,
+ 1,
+ m_mvpMatrixCbuffer.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(color.r * 255.0f)));
+ unsigned int g = max(0, min(255, static_cast(color.g * 255.0f)));
+ unsigned int b = max(0, min(255, static_cast(color.b * 255.0f)));
+ unsigned int a = max(0, min(255, static_cast(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
+ )
+{
+ Draw(
+ texture,
+ position,
+ positionUnits,
+ size,
+ sizeUnits,
+ color,
+ rotation,
+ blendMode,
+ float4(0.0f, 1.0f, 0.0f, 1.0f),
+ Vector4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF)
+ );
+}
+
+
+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,
+ _In_ float4 textRect,
+ _In_ Vector4 colors
+ )
+{
+ // 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);
+ m_instanceData[m_numSpritesDrawn].textRect = textRect;
+ m_instanceData[m_numSpritesDrawn].colors = colors;
+ }
+ 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/JGE/src/DirectX/BasicSprites.h b/JGE/src/DirectX/BasicSprites.h
new file mode 100644
index 000000000..817c5bdf1
--- /dev/null
+++ b/JGE/src/DirectX/BasicSprites.h
@@ -0,0 +1,195 @@
+//// 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
+#include