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 +#include + +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; + float4 textRect; + Vector4 colors; + float4 pt_x; + float4 pt_y; + unsigned int color; + }; + + struct TextureMapElement + { + Microsoft::WRL::ComPtr srv; + float2 size; + }; + + struct SpriteRunInfo + { + ID3D11ShaderResourceView* textureView; + ID3D11BlendState1* blendState; + unsigned int numSprites; + }; + + ref class SpriteBatch + { + internal: + SpriteBatch(); + void Initialize( + _In_ ID3D11Device1* d3dDevice, + _In_ int capacity = 1024 + ); + 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 + ); + 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, + _In_ float4 textRect, + _In_ Vector4 colors + ); + + 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 m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_instanceDataBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_blendStateAlpha; + Microsoft::WRL::ComPtr m_blendStateAdditive; + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_geometryShader; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_linearSampler; + Microsoft::WRL::ComPtr m_renderTargetInfoCbuffer; + Microsoft::WRL::ComPtr m_mvpMatrixCbuffer; + + std::unique_ptr m_vertexData; + std::unique_ptr m_instanceData; + std::map m_textureMap; + std::vector m_spriteRuns; + + RenderTechnique m_technique; + ID3D11ShaderResourceView* m_currentTextureView; + ID3D11BlendState1* m_currentBlendState; + float2 m_renderTargetSize; + float4x4 m_mvpMatrix; + + int m_capacity; + int m_spritesInRun; + int m_numSpritesDrawn; + float m_dpi; + }; +} diff --git a/JGE/src/DirectX/BasicSprites.ps.hlsl b/JGE/src/DirectX/BasicSprites.ps.hlsl new file mode 100644 index 000000000..e7da5dd03 --- /dev/null +++ b/JGE/src/DirectX/BasicSprites.ps.hlsl @@ -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/JGE/src/DirectX/JGfx - Copy.cpp b/JGE/src/DirectX/JGfx - Copy.cpp new file mode 100644 index 000000000..be06393f3 --- /dev/null +++ b/JGE/src/DirectX/JGfx - Copy.cpp @@ -0,0 +1,1495 @@ +//------------------------------------------------------------------------------------- +// +// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows. +// +// Licensed under the BSD license, see LICENSE in root folder for details. +// +// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) +// +//------------------------------------------------------------------------------------- +#if (!defined IOS) && (!defined QT_CONFIG) +#if (defined WIN32) && (!defined WP8) +#pragma warning(disable : 4786) +#pragma comment( lib, "giflib.lib" ) +#endif + +#ifdef WP8 +#define _XM_NO_INTRINSICS_ +#include +#include +#include +#include +#include +#include + +//using namespace DirectX; +using namespace Microsoft::WRL; +using namespace DirectX; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; + +_declspec(align(16)) struct MatrixBufferType +{ + DirectX::XMMATRIX mvpMatrix; +}; + +_declspec(align(16)) struct VertexType +{ + DirectX::XMFLOAT3 position; + DirectX::XMFLOAT4 color; + DirectX::XMFLOAT2 texture; +}; +_declspec(align(16)) struct TextureColorType +{ + bool istexture[16]; +}; + +namespace DX +{ + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + throw Platform::Exception::CreateException(hr); + } + } + + // Function that reads from a binary file asynchronously. + inline Concurrency::task^> ReadDataAsync(Platform::String^ filename) + { + using namespace Windows::Storage; + using namespace Concurrency; + + auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation; + + return create_task(folder->GetFileAsync(filename)).then([] (StorageFile^ file) + { + return FileIO::ReadBufferAsync(file); + }).then([] (Streams::IBuffer^ fileBuffer) -> Platform::Array^ + { + auto fileData = ref new Platform::Array(fileBuffer->Length); + Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(fileData); + return fileData; + }); + } +} +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define XMD_H +#include + +#ifdef __cplusplus +} +#endif +#endif //IOS + +#include "../../include/JGE.h" +#include "../../include/JRenderer.h" +#include "../../include/JResourceManager.h" +#include "../../include/JFileSystem.h" +#include "../../include/JAssert.h" + +#if (defined WIN32) && (!defined QT_CONFIG) +#ifndef __attribute__ +#define __attribute__((a)) +#endif +#endif + + + +JQuad::JQuad(JTexture *tex, float x, float y, float width, float height) + :mTex(tex), mX(x), mY(y), mWidth(width), mHeight(height) +{ + JASSERT(tex != NULL); + JRenderer::GetInstance()->TransferTextureToGLContext(*tex); + + mHotSpotX = 0.0f; + mHotSpotY = 0.0f; + //mBlend = BLEND_DEFAULT; + for (int i=0;i<4;i++) + mColor[i].color = 0xFFFFFFFF; + + mHFlipped = false; + mVFlipped = false; + + SetTextureRect(x, y, width, height); +} + +void JQuad::SetTextureRect(float x, float y, float w, float h) +{ + mX = x; + mY = y; + mWidth = w; + mHeight = h; + + mTX0 = x/mTex->mTexWidth; + mTY0 = y/mTex->mTexHeight; + mTX1 = (x+w)/mTex->mTexWidth; + mTY1 = (y+h)/mTex->mTexHeight; +} + + +void JQuad::GetTextureRect(float *x, float *y, float *w, float *h) +{ + *x=mX; *y=mY; *w=mWidth; *h=mHeight; +} + + +void JQuad::SetColor(PIXEL_TYPE color) +{ + for (int i=0;i<4;i++) + mColor[i].color = color; +} + + + +void JQuad::SetHotSpot(float x, float y) +{ + mHotSpotX = x; + mHotSpotY = y; +} + + +////////////////////////////////////////////////////////////////////////// + +JTexture::JTexture() : mBuffer(NULL) +{ + mTexId = (ID3D11ShaderResourceView*)-1; +} + +JTexture::~JTexture() +{ + if (mBuffer) + { + delete [] mBuffer; + mBuffer = NULL; + } +} + + +void JTexture::UpdateBits(int x, int y, int width, int height, PIXEL_TYPE* bits) +{ +} + +////////////////////////////////////////////////////////////////////////// + +JRenderer* JRenderer::mInstance = NULL; +bool JRenderer::m3DEnabled = false; + +void JRenderer::Set3DFlag(bool flag) { m3DEnabled = flag; } + +JRenderer* JRenderer::GetInstance() +{ + if (mInstance == NULL) + { + mInstance = new JRenderer(); + + JASSERT(mInstance != NULL); + + mInstance->InitRenderer(); + } + + return mInstance; +} + + +void JRenderer::Destroy() +{ + if (mInstance) + { + mInstance->DestroyRenderer(); + delete mInstance; + mInstance = NULL; + } +} + +JRenderer::JRenderer() + : mActualWidth(SCREEN_WIDTH_F), + mActualHeight(SCREEN_HEIGHT_F), + mWindowWidth(0), + mWindowHeight(0), + m_Window(0), + m_vertexShader(0), + m_pixelShader(0), + m_layout(0), + m_sampleState(0), + m_matrixBuffer(0) +{ + m_mvpMatrix = XMMatrixIdentity(); +} + + +JRenderer::~JRenderer() +{ + if(m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } +} + + +void JRenderer::InitRenderer() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#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 Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + DX::ThrowIfFailed( + D3D11CreateDevice( + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + creationFlags, // Set set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &device, // Returns the Direct3D device created. + &m_featureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ) + ); + + // Get the Direct3D 11.1 API device and context interfaces. + DX::ThrowIfFailed( + device.As(&m_d3dDevice) + ); + + DX::ThrowIfFailed( + context.As(&m_d3dContext) + ); + + // Buffer Init + D3D11_BUFFER_DESC vertexBufferDesc; + + // Set up the description of the static vertex buffer. + vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + vertexBufferDesc.ByteWidth = sizeof(VertexType)*4; + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + // Now create the vertex buffer. + DX::ThrowIfFailed(m_d3dDevice->CreateBuffer(&vertexBufferDesc, NULL, &m_vertexBuffer)); + + unsigned short indices[] = { + 0, 1, 2, + 0, 2, 3, + }; + + D3D11_BUFFER_DESC indexBufferDesc; + D3D11_SUBRESOURCE_DATA indexData; + ZeroMemory( &indexBufferDesc, sizeof(indexBufferDesc) ); + + indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + indexBufferDesc.ByteWidth = sizeof(indices); + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + + indexData.pSysMem = indices; + DX::ThrowIfFailed(m_d3dDevice->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer)); + + // vertex and shader mess + // Creates shaders + auto loadVSTask = DX::ReadDataAsync("SimpleVertexShader.cso"); + auto loadPSTask = DX::ReadDataAsync("SimplePixelShader.cso"); + + auto createVSTask = loadVSTask.then([this](Platform::Array^ fileData) { + DX::ThrowIfFailed( + m_d3dDevice->CreateVertexShader( + fileData->Data, + fileData->Length, + nullptr, + &m_vertexShader + ) + ); + + const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + DX::ThrowIfFailed( + m_d3dDevice->CreateInputLayout( + vertexDesc, + ARRAYSIZE(vertexDesc), + fileData->Data, + fileData->Length, + &m_layout + ) + ); + }); + + auto createPSTask = loadPSTask.then([this](Platform::Array^ fileData) { + DX::ThrowIfFailed( + m_d3dDevice->CreatePixelShader( + fileData->Data, + fileData->Length, + nullptr, + &m_pixelShader + ) + ); + + CD3D11_BUFFER_DESC matrixBufferDesc; + ZeroMemory( &matrixBufferDesc, sizeof( D3D11_BUFFER_DESC ) ); + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + DX::ThrowIfFailed( + m_d3dDevice->CreateBuffer( + &matrixBufferDesc, + nullptr, + &m_matrixBuffer + ) + ); + }); + + + D3D11_BUFFER_DESC textureColorBufferDesc; + ZeroMemory( &textureColorBufferDesc, sizeof( D3D11_BUFFER_DESC ) ); + textureColorBufferDesc.Usage = D3D11_USAGE_DEFAULT; + textureColorBufferDesc.ByteWidth = sizeof(TextureColorType); + textureColorBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + //textureColorBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + textureColorBufferDesc.MiscFlags = 0; + textureColorBufferDesc.StructureByteStride = 0; + DX::ThrowIfFailed( + m_d3dDevice->CreateBuffer(&textureColorBufferDesc, NULL, &m_textureColorBuffer) + ); + + // Sample state description + D3D11_SAMPLER_DESC samplerDesc; + ZeroMemory(&samplerDesc,sizeof(D3D11_SAMPLER_DESC)); + + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + DX::ThrowIfFailed(m_d3dDevice->CreateSamplerState(&samplerDesc, &m_sampleState)); +} + +void JRenderer::OnWindowsSizeChanged(void* window, float inWidth, float inHeight) +{ + if (mWindowWidth != inWidth || + mWindowHeight != inHeight +// || m_orientation != DisplayProperties::CurrentOrientation + ) + { + mWindowWidth = inWidth; + mWindowHeight = inHeight; + if(window != NULL) + m_Window = (IUnknown*)window; + + + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + m_renderTargetView = nullptr; + m_depthStencilView = nullptr; + m_d3dContext->Flush(); + + if(m_swapChain != nullptr) + { + // If the swap chain already exists, resize it. + DX::ThrowIfFailed( + m_swapChain->ResizeBuffers( + 2, // Double-buffered swap chain. + static_cast(mWindowWidth), + static_cast(mWindowHeight), + DXGI_FORMAT_B8G8R8A8_UNORM, + 0 + ) + ); + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = static_cast(mWindowWidth); // Match the size of the window. + swapChainDesc.Height = static_cast(mWindowHeight); + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain 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 minimize latency. + swapChainDesc.Scaling = DXGI_SCALING_NONE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect. + swapChainDesc.Flags = 0; + + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + + ComPtr dxgiFactory; + DX::ThrowIfFailed( + dxgiAdapter->GetParent( + __uuidof(IDXGIFactory2), + &dxgiFactory + ) + ); + +// Windows::UI::Core::CoreWindow* window = (Windows::UI::Core::CoreWindow*)window.Get(); + DX::ThrowIfFailed( + dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_Window.Get(), + &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) + ); + } + /* + // Set the proper orientation for the swap chain, and generate the + // 3D matrix transformation for rendering to the rotated swap chain. + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + switch (m_orientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + break; + + default: + throw ref new Platform::FailureException(); + } + + DX::ThrowIfFailed( + m_swapChain->SetRotation(rotation) + ); + */ + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + DX::ThrowIfFailed( + m_swapChain->GetBuffer( + 0, + __uuidof(ID3D11Texture2D), + &backBuffer + ) + ); + + DX::ThrowIfFailed( + m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + &m_renderTargetView + ) + ); + + // Create a depth stencil view. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_D24_UNORM_S8_UINT, + static_cast(mWindowWidth), + static_cast(mWindowHeight), + 1, + 1, + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + DX::ThrowIfFailed( + m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + &depthStencil + ) + ); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed( + m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + &m_depthStencilView + ) + ); + + + // Setup the raster description which will determine how and what polygons will be drawn. + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.AntialiasedLineEnable = false; + rasterDesc.CullMode = D3D11_CULL_BACK; + rasterDesc.DepthBias = 0; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = true; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.FrontCounterClockwise = false; + rasterDesc.MultisampleEnable = false; + rasterDesc.ScissorEnable = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + + // Create the rasterizer state from the description we just filled out. + DX::ThrowIfFailed(m_d3dDevice->CreateRasterizerState(&rasterDesc, &m_rasterState)); + + // Now set the rasterizer state. + m_d3dContext->RSSetState(m_rasterState.Get()); + + + // Set the rendering viewport to target the entire window. + CD3D11_VIEWPORT viewport( + 0.0f, + 0.0f, + SCREEN_WIDTH, //mWindowWidth, + SCREEN_HEIGHT //mWindowHeight +// -1.0f, +// 1.0f + ); + + m_d3dContext->RSSetViewports(1, &viewport); + } +} + + +void JRenderer::DestroyRenderer() +{ +} + +void JRenderer::BeginScene() +{ + float color[4]; + + + // Setup the color to clear the buffer to. + color[0] = 0; + color[1] = 0; + color[2] = 255; + color[3] = 0; + + // Clear the back buffer. + m_d3dContext->ClearRenderTargetView(m_renderTargetView.Get(), color); + + // Clear the depth buffer. + m_d3dContext->ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); + + m_d3dContext->OMSetRenderTargets( + 1, + m_renderTargetView.GetAddressOf(), + m_depthStencilView.Get() + ); + + XMMATRIX tmpMatrix; + tmpMatrix = XMMatrixOrthographicOffCenterRH(0.0f, SCREEN_WIDTH_F, 0.0f, SCREEN_HEIGHT_F-1.0f, -1.0f, 1.0f); + m_mvpMatrix = XMMatrixMultiply(tmpMatrix, XMMatrixIdentity()); +} + + +void JRenderer::EndScene() +{ + // The application may optionally specify "dirty" or "scroll" + // rects to improve efficiency in certain scenarios. + DXGI_PRESENT_PARAMETERS parameters = {0}; + parameters.DirtyRectsCount = 0; + parameters.pDirtyRects = nullptr; + parameters.pScrollRect = nullptr; + parameters.pScrollOffset = nullptr; + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present1(1, 0, ¶meters); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be entirely + // overwritten. If dirty or scroll rects are used, this call should be removed. +// m_d3dContext->DiscardView(m_renderTargetView.Get()); + + // Discard the contents of the depth stencil. +// m_d3dContext->DiscardView(m_depthStencilView.Get()); + + // If the device was removed either by a disconnect or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED) + { + // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources. + float width = mWindowWidth; + float height = mWindowHeight; + + mWindowWidth = 0; + mWindowHeight = 0; + m_swapChain = nullptr; + + InitRenderer(); + OnWindowsSizeChanged(NULL, width, height); + } + else + { + DX::ThrowIfFailed(hr); + } +} + +void JRenderer::BindTexture(JTexture *tex) +{ +} + + +void JRenderer::EnableTextureFilter(bool flag) +{ + if (flag) + mCurrentTextureFilter = TEX_FILTER_LINEAR; + else + mCurrentTextureFilter = TEX_FILTER_NEAREST; +} + +void Swap(float *a, float *b) +{ + float n=*a; + *a = *b; + *b = n; +} + +void JRenderer::RenderQuad(JQuad* quad, float xo, float yo, float angle, float xScale, float yScale) +{ + float width = quad->mWidth; + float height = quad->mHeight; + float x = -quad->mHotSpotX; + float y = quad->mHotSpotY; + + VertexType* verticesTmp; + // Create the vertex array. + verticesTmp = new VertexType[4]; + if(!verticesTmp) + { + return ; + } + + verticesTmp[0].position = XMFLOAT3(x, y-height, 0.0f); + verticesTmp[1].position = XMFLOAT3(x+width, y-height, 0.0f); + verticesTmp[2].position = XMFLOAT3(x+width, y, 0.0f); + verticesTmp[3].position = XMFLOAT3(x, y, 0.0f); + + verticesTmp[0].texture = XMFLOAT2(quad->mTX0, quad->mTY1); + verticesTmp[1].texture = XMFLOAT2(quad->mTX1, quad->mTY1); + verticesTmp[2].texture = XMFLOAT2(quad->mTX0, quad->mTY0); + verticesTmp[3].texture = XMFLOAT2(quad->mTX1, quad->mTY0); + + verticesTmp[0].color = XMFLOAT4(quad->mColor[0].r/255.0f, quad->mColor[0].g/255.0f, quad->mColor[0].b/255.0f, quad->mColor[0].a/255.0f); + verticesTmp[1].color = XMFLOAT4(quad->mColor[1].r/255.0f, quad->mColor[1].g/255.0f, quad->mColor[1].b/255.0f, quad->mColor[1].a/255.0f); + verticesTmp[2].color = XMFLOAT4(quad->mColor[3].r/255.0f, quad->mColor[3].g/255.0f, quad->mColor[3].b/255.0f, quad->mColor[3].a/255.0f); + verticesTmp[3].color = XMFLOAT4(quad->mColor[2].r/255.0f, quad->mColor[2].g/255.0f, quad->mColor[2].b/255.0f, quad->mColor[2].a/255.0f); + + + D3D11_MAPPED_SUBRESOURCE mappedResource; + VertexType* verticesPtr; + if(FAILED(m_d3dContext->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))){return ;} + verticesPtr = (VertexType*)mappedResource.pData; + memcpy(verticesPtr, (void*)verticesTmp, (sizeof(VertexType) * 4)); + m_d3dContext->Unmap(m_vertexBuffer, 0); + + if ( verticesTmp ) + { + delete[] verticesTmp; + verticesTmp = 0; + } + + + //////////////////////// + unsigned int stride; + unsigned int offset; + // Set vertex buffer stride and offset. + stride = sizeof(VertexType); + offset = 0; + + // Set the vertex buffer to active in the input assembler so it can be rendered. + m_d3dContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); + + m_d3dContext->IASetIndexBuffer( m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); + + + // Set the sampler state in the pixel shader. + m_d3dContext->PSSetSamplers(0, 1, &m_sampleState); + + // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. + m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + + MatrixBufferType* dataPtr; + ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE)); + +// Transpose the matrices to prepare them for the shader. + XMMATRIX tmpMatrix = XMMatrixMultiply(XMMatrixTranslation(xo,yo,0.0f),m_mvpMatrix); + tmpMatrix = XMMatrixMultiply(XMMatrixRotationX(angle), tmpMatrix); + tmpMatrix = XMMatrixMultiply(XMMatrixScaling(xScale, yScale, 1.0f), tmpMatrix); + + // Lock the constant buffer so it can be written to. + DX::ThrowIfFailed(m_d3dContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)); + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->mvpMatrix = tmpMatrix; + + // Unlock the constant buffer. + m_d3dContext->Unmap(m_matrixBuffer, 0); + + // Now set the constant buffer in the vertex shader with the updated values. + m_d3dContext->VSSetConstantBuffers(0, 1, &m_matrixBuffer); + + + TextureColorType tc; + ZeroMemory(&tc, sizeof(tc)); + tc.istexture[0] = TRUE; + m_d3dContext->UpdateSubresource(m_textureColorBuffer, 0, 0, &tc, 0, 0); + m_d3dContext->PSSetConstantBuffers(0, 1, &m_textureColorBuffer); + + + // Set shader texture resource in the pixel shader. + m_d3dContext->PSSetShaderResources(0, 1, &(quad->mTex->mTexId)); + + // Set the vertex input layout. + m_d3dContext->IASetInputLayout(m_layout.Get()); + + // Set the vertex and pixel shaders that will be used to render this triangle. + m_d3dContext->VSSetShader(m_vertexShader.Get(), NULL, 0); + m_d3dContext->PSSetShader(m_pixelShader.Get(), NULL, 0); + + // Render the triangle. + m_d3dContext->DrawIndexed( 6, 0, 0 ); + +} + + +void JRenderer::RenderQuad(JQuad* quad, VertexColor* pt) +{ +} + + +void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE color) +{ + +} + + +void JRenderer::DrawRect(float x, float y, float width, float height, PIXEL_TYPE color) +{ +} + + +void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE* colors) +{ + JColor col[4]; + for (int i=0;i<4;i++) + col[i].color = colors[i]; + + FillRect(x, y, width, height, col); +} + +void JRenderer::FillRect(float x, float y, float width, float height, JColor* colors) +{ +} + + +void JRenderer::DrawLine(float x1, float y1, float x2, float y2, PIXEL_TYPE color) +{ + +} + + +void JRenderer::PlotArray(float *x, float *y, int count, PIXEL_TYPE color) +{ + +} + + + +void JRenderer::ScreenShot(const char* filename __attribute__((unused))) +{ + +} + + +static int getNextPower2(int width) +{ + int b = width; + int n; + for (n = 0; b != 0; n++) b >>= 1; + b = 1 << n; + if (b == 2 * width) b >>= 1; + return b; +} + + +static void jpg_null(j_decompress_ptr cinfo __attribute__((unused))) +{ +} + + +static boolean jpg_fill_input_buffer(j_decompress_ptr cinfo __attribute__((unused))) +{ + //// ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n"); + return 1; +} + +static void jpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + + cinfo->src->next_input_byte += (size_t) num_bytes; + cinfo->src->bytes_in_buffer -= (size_t) num_bytes; + + //// if (cinfo->src->bytes_in_buffer < 0) + //// ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n"); +} + +static void jpeg_mem_src(j_decompress_ptr cinfo, byte *mem, int len) +{ + cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr)); + cinfo->src->init_source = jpg_null; + cinfo->src->fill_input_buffer = jpg_fill_input_buffer; + cinfo->src->skip_input_data = jpg_skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; + cinfo->src->term_source = jpg_null; + cinfo->src->bytes_in_buffer = len; + cinfo->src->next_input_byte = mem; +} + +/* +============== +LoadJPG +============== +*/ +void JRenderer::LoadJPG(TextureInfo &textureInfo, const char *filename, int mode __attribute__((unused)), int TextureFormat __attribute__((unused))) +{ + textureInfo.mBits = NULL; + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + BYTE *rawdata, *rgbadata, *scanline, *p, *q; + int rawsize, i; + + JFileSystem* fileSystem = JFileSystem::GetInstance(); + if (!fileSystem->OpenFile(filename)) return; + + rawsize = fileSystem->GetFileSize(); + + rawdata = new BYTE[rawsize]; + + if (!rawdata) + { + fileSystem->CloseFile(); + return; + } + + fileSystem->ReadFile(rawdata, rawsize); + fileSystem->CloseFile(); + + // Initialize libJpeg Object + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, rawdata, rawsize); + + // Process JPEG header + jpeg_read_header(&cinfo, true); + + + + // Start Decompression + jpeg_start_decompress(&cinfo); + + // Check Colour Components + if(cinfo.output_components != 3 && cinfo.output_components != 4) + { + //// ri.Con_Printf(PRINT_ALL, "Invalid JPEG colour components\n"); + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + return; + } + + int tw = getNextPower2(cinfo.output_width); + int th = getNextPower2(cinfo.output_height); + + + // Allocate Memory for decompressed image + rgbadata = new BYTE[tw * th * 4]; + if(!rgbadata) + { + //// ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG buffer\n"); + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + delete [] rgbadata; + return; + } + + + // Pass sizes to output + + // Allocate Scanline buffer + scanline = (byte *)malloc(cinfo.output_width * 3); + if(!scanline) + { + //// ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG scanline buffer\n"); + + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + + delete [] rgbadata; + return; + } + + // Read Scanlines, and expand from RGB to RGBA + BYTE* currRow = rgbadata; + + while(cinfo.output_scanline < cinfo.output_height) + { + p = scanline; + jpeg_read_scanlines(&cinfo, &scanline, 1); + + q = currRow; + for(i=0; i<(int)cinfo.output_width; i++) + { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + q[3] = 255; + + p+=3; q+=4; + } + currRow += tw*4; + } + + // Free the scanline buffer + free(scanline); + + textureInfo.mBits = rgbadata; + textureInfo.mWidth = cinfo.output_width; + textureInfo.mHeight = cinfo.output_height; + textureInfo.mTexWidth = tw; + textureInfo.mTexHeight = th; + + // Finish Decompression + try { + jpeg_finish_decompress(&cinfo); + } catch(...) {} + + // Destroy JPEG object + jpeg_destroy_decompress(&cinfo); + + delete[] rawdata; +} + + +static void PNGCustomWarningFn(png_structp png_ptr __attribute__((unused)), png_const_charp warning_msg __attribute__((unused))) +{ + // ignore PNG warnings +} + + +static void PNGCustomReadDataFn(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + JFileSystem *fileSystem = (JFileSystem*)png_ptr->io_ptr; + + check = fileSystem->ReadFile(data, length); + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} + +JTexture* JRenderer::LoadTexture(const char* filename, int mode, int TextureFormat __attribute__((unused))) +{ + TextureInfo textureInfo; + + textureInfo.mBits = NULL; + + if (strstr(filename, ".jpg")!=NULL || strstr(filename, ".JPG")!=NULL) + LoadJPG(textureInfo, filename); +#if (!defined IOS) && (!defined QT_CONFIG) && (!defined SDL_CONFIG) && (!defined WP8) + else if(strstr(filename, ".gif")!=NULL || strstr(filename, ".GIF")!=NULL) + LoadGIF(textureInfo,filename); +#endif + else if(strstr(filename, ".png")!=NULL || strstr(filename, ".PNG")!=NULL) + LoadPNG(textureInfo, filename); + + if (textureInfo.mBits == NULL) { + printf("Texture %s failed to load\n", filename); + return NULL; + } + + bool ret = false; + + JTexture *tex = new JTexture(); + + if (tex) + { + if (mImageFilter != NULL) + mImageFilter->ProcessImage((PIXEL_TYPE*)textureInfo.mBits, textureInfo.mWidth, textureInfo.mHeight); + + tex->mFilter = TEX_FILTER_LINEAR; + tex->mWidth = textureInfo.mWidth; + tex->mHeight = textureInfo.mHeight; + tex->mTexWidth = textureInfo.mTexWidth; + tex->mTexHeight = textureInfo.mTexHeight; + + tex->mBuffer = textureInfo.mBits; + } + + return tex; +} + +int JRenderer::LoadPNG(TextureInfo &textureInfo, const char *filename, int mode __attribute__((unused)), int TextureFormat __attribute__((unused))) +{ + textureInfo.mBits = NULL; + + DWORD* p32; + + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height, tw, th; + int bit_depth, color_type, interlace_type, x, y; + DWORD* line; + + JFileSystem* fileSystem = JFileSystem::GetInstance(); + if (!fileSystem->OpenFile(filename)) + return JGE_ERR_CANT_OPEN_FILE; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + { + fileSystem->CloseFile(); + + return JGE_ERR_PNG; + } + + png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, PNGCustomWarningFn); + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + //fclose(fp); + fileSystem->CloseFile(); + + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + + return JGE_ERR_PNG; + } + png_init_io(png_ptr, NULL); + png_set_read_fn(png_ptr, (png_voidp)fileSystem, PNGCustomReadDataFn); + + png_set_sig_bytes(png_ptr, sig_read); + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); + png_set_strip_16(png_ptr); + png_set_packing(png_ptr); + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + line = (DWORD*) malloc(width * 4); + if (!line) + { + //fclose(fp); + fileSystem->CloseFile(); + + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + return JGE_ERR_MALLOC_FAILED; + } + + + tw = getNextPower2(width); + th = getNextPower2(height); + + int size = tw * th * 4; // RGBA + + BYTE* buffer = new BYTE[size]; + + //JTexture *tex = new JTexture(); + + if (buffer) + { + + + p32 = (DWORD*) buffer; + + for (y = 0; y < (int)height; y++) + { + png_read_row(png_ptr, (BYTE*) line, png_bytep_NULL); + for (x = 0; x < (int)width; x++) + { + DWORD color32 = line[x]; + int a = (color32 >> 24) & 0xff; + int r = color32 & 0xff; + int g = (color32 >> 8) & 0xff; + int b = (color32 >> 16) & 0xff; + + color32 = r | (g << 8) | (b << 16) | (a << 24); + *(p32+x) = color32; + + } + p32 += tw; + + } + + } + + + free (line); + + png_read_end(png_ptr, info_ptr); + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + fileSystem->CloseFile(); + + + textureInfo.mBits = buffer; + textureInfo.mWidth = width; + textureInfo.mHeight = height; + textureInfo.mTexWidth = tw; + textureInfo.mTexHeight = th; + + return 1; + //return textureInfo; + +} + + + + +void JRenderer::TransferTextureToGLContext(JTexture& inTexture) +{ + if (inTexture.mBuffer != NULL) + { + D3D11_TEXTURE2D_DESC desc; + HRESULT hr = E_FAIL; + + desc.Width = static_cast( inTexture.mTexWidth ); + desc.Height = static_cast( inTexture.mTexHeight ); + desc.MipLevels = static_cast( 1 ); + desc.ArraySize = static_cast( 1 ); + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = inTexture.mBuffer; + initData.SysMemPitch = inTexture.mTexWidth*4; + initData.SysMemSlicePitch = inTexture.mTexHeight*inTexture.mTexWidth*4; + + ID3D11Texture2D* tex2D = nullptr; + hr = m_d3dDevice->CreateTexture2D( &desc, &initData, &tex2D); + if( S_OK != hr) + return; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + D3D11_TEXTURE2D_DESC desc1; + // Get a texture description to determine the texture + // format of the loaded texture. + tex2D->GetDesc( &desc1 ); + + // Fill in the D3D11_SHADER_RESOURCE_VIEW_DESC structure. + srvDesc.Format = desc1.Format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = desc1.MipLevels; + + // Create the shader resource view. + m_d3dDevice->CreateShaderResourceView( tex2D, &srvDesc, &inTexture.mTexId); + + delete [] inTexture.mBuffer; + inTexture.mBuffer = NULL; + } +} + +JTexture* JRenderer::CreateTexture(int width, int height, int mode __attribute__((unused))) +{ + JTexture *tex = new JTexture(); + HRESULT hr = E_FAIL; + + if (tex) + { + int size = width * height * sizeof(PIXEL_TYPE); // RGBA + BYTE* buffer = new BYTE[size]; + if (buffer) + { + tex->mFilter = TEX_FILTER_LINEAR; + tex->mWidth = width; + tex->mHeight = height; + tex->mTexWidth = width; + tex->mTexHeight = height; + tex->mBuffer = buffer; + + TransferTextureToGLContext(*tex); + } + else + { + delete tex; + tex = NULL; + } + } + + return tex; +} + + +void JRenderer::EnableVSync(bool flag __attribute__((unused))) +{ + // if (flag) + // hge->System_SetState(HGE_FPS, 60); // HGEFPS_VSYNC + // else + // hge->System_SetState(HGE_FPS, HGEFPS_UNLIMITED); +} + + +void JRenderer::ClearScreen(PIXEL_TYPE color) +{ + +} + + +void JRenderer::SetTexBlend(int src, int dest) +{ + +} + + +void JRenderer::SetTexBlendSrc(int src) +{// NOT USED + +} + + +void JRenderer::SetTexBlendDest(int dest) +{// NOT USED + +} + + +void JRenderer::Enable2D() +{// NOT USED + if (mCurrentRenderMode == MODE_2D) + return; + + mCurrentRenderMode = MODE_2D; + + +} + + +void JRenderer::Enable3D() +{ /* NOT USED */ +} + + +void JRenderer::SetClip(int, int, int, int) +{// NOT USED +} + +void JRenderer::LoadIdentity() +{// NOT USED +} + +void JRenderer::Translate(float, float, float) +{// NOT USED +} + +void JRenderer::RotateX(float) +{// NOT USED +} + +void JRenderer::RotateY(float) +{// NOT USED +} + +void JRenderer::RotateZ(float) +{// NOT USED +} + + +void JRenderer::PushMatrix() +{// NOT USED +} + +void JRenderer::PopMatrix() +{// NOT USED +} + +void JRenderer::RenderTriangles(JTexture* texture, Vertex3D *vertices, int start, int count) +{// NOT USED + +} + + +void JRenderer::SetFOV(float fov) +{// NOT USED + mFOV = fov; +} + + +void JRenderer::FillPolygon(float* x, float* y, int count, PIXEL_TYPE color) +{// NOT USED + +} + + +void JRenderer::DrawPolygon(float* x, float* y, int count, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::DrawLine(float x1, float y1, float x2, float y2, float lineWidth, PIXEL_TYPE color) +{// NOT USED + float dy=y2-y1; + float dx=x2-x1; + if(dy==0 && dx==0) + return; + + float l=(float)hypot(dx,dy); + + float x[4]; + float y[4]; + + x[0]=x1+lineWidth*(y2-y1)/l; + y[0]=y1-lineWidth*(x2-x1)/l; + + x[1]=x1-lineWidth*(y2-y1)/l; + y[1]=y1+lineWidth*(x2-x1)/l; + + x[2]=x2-lineWidth*(y2-y1)/l; + y[2]=y2+lineWidth*(x2-x1)/l; + + x[3]=x2+lineWidth*(y2-y1)/l; + y[3]=y2-lineWidth*(x2-x1)/l; + + FillPolygon(x, y, 4, color); +} + + +void JRenderer::DrawCircle(float x, float y, float radius, PIXEL_TYPE color) +{// NOT USED +} + +void JRenderer::FillCircle(float x, float y, float radius, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::DrawPolygon(float x, float y, float size, int count, float startingAngle, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::FillPolygon(float x, float y, float size, int count, float startingAngle, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::SetImageFilter(JImageFilter* imageFilter) +{ + mImageFilter = imageFilter; +} + + + +void JRenderer::DrawRoundRect(float x, float y, float w, float h, float radius, PIXEL_TYPE color) +{// NOT USED +} + + + +void JRenderer::FillRoundRect(float x, float y, float w, float h, float radius, PIXEL_TYPE color) +{// NOT USED +} + diff --git a/JGE/src/DirectX/JGfx.cpp b/JGE/src/DirectX/JGfx.cpp new file mode 100644 index 000000000..8d34293fc --- /dev/null +++ b/JGE/src/DirectX/JGfx.cpp @@ -0,0 +1,1351 @@ +//------------------------------------------------------------------------------------- +// +// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows. +// +// Licensed under the BSD license, see LICENSE in root folder for details. +// +// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) +// +//------------------------------------------------------------------------------------- +#if (!defined IOS) && (!defined QT_CONFIG) +#if (defined WIN32) && (!defined WP8) +#pragma warning(disable : 4786) +#pragma comment( lib, "giflib.lib" ) +#endif + +#ifdef WP8 +#include +#include +#include +#include +#include +#include +#include +#include "BasicSprites.h" +#include +using namespace BasicSprites; +using namespace Microsoft::WRL; +using namespace DirectX; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define XMD_H +#include + +#ifdef __cplusplus +} +#endif +#endif //IOS + +#include "../../include/JGE.h" +#include "../../include/JRenderer.h" +#include "../../include/JResourceManager.h" +#include "../../include/JFileSystem.h" +#include "../../include/JAssert.h" + +#if (defined WIN32) && (!defined QT_CONFIG) +#ifndef __attribute__ +#define __attribute__((a)) +#endif +#endif + +typedef float4x4 ESMatrix; +typedef float GLfloat; + +void esMatrixLoadIdentity(ESMatrix *result) +{ + memset(result, 0x0, sizeof(ESMatrix)); + (*result)[0][0] = 1.0f; + (*result)[1][1] = 1.0f; + (*result)[2][2] = 1.0f; + (*result)[3][3] = 1.0f; +} + +void esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz) +{ + (*result)[0][0] *= sx; + (*result)[0][1] *= sx; + (*result)[0][2] *= sx; + (*result)[0][3] *= sx; + + (*result)[1][0] *= sy; + (*result)[1][1] *= sy; + (*result)[1][2] *= sy; + (*result)[1][3] *= sy; + + (*result)[2][0] *= sz; + (*result)[2][1] *= sz; + (*result)[2][2] *= sz; + (*result)[2][3] *= sz; +} + +void esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz) +{ + (*result)[3][0] += ((*result)[0][0] * tx + (*result)[1][0] * ty + (*result)[2][0] * tz); + (*result)[3][1] += ((*result)[0][1] * tx + (*result)[1][1] * ty + (*result)[2][1] * tz); + (*result)[3][2] += ((*result)[0][2] * tx + (*result)[1][2] * ty + (*result)[2][2] * tz); + (*result)[3][3] += ((*result)[0][3] * tx + (*result)[1][3] * ty + (*result)[2][3] * tz); +} + +void esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB) +{ + ESMatrix tmp; + int i; + + for (i=0; i<4; i++) + { + tmp[i][0] = ((*srcA)[i][0] * (*srcB)[0][0]) + + ((*srcA)[i][1] * (*srcB)[1][0]) + + ((*srcA)[i][2] * (*srcB)[2][0]) + + ((*srcA)[i][3] * (*srcB)[3][0]) ; + + tmp[i][1] = ((*srcA)[i][0] * (*srcB)[0][1]) + + ((*srcA)[i][1] * (*srcB)[1][1]) + + ((*srcA)[i][2] * (*srcB)[2][1]) + + ((*srcA)[i][3] * (*srcB)[3][1]) ; + + tmp[i][2] = ((*srcA)[i][0] * (*srcB)[0][2]) + + ((*srcA)[i][1] * (*srcB)[1][2]) + + ((*srcA)[i][2] * (*srcB)[2][2]) + + ((*srcA)[i][3] * (*srcB)[3][2]) ; + + tmp[i][3] = ((*srcA)[i][0] * (*srcB)[0][3]) + + ((*srcA)[i][1] * (*srcB)[1][3]) + + ((*srcA)[i][2] * (*srcB)[2][3]) + + ((*srcA)[i][3] * (*srcB)[3][3]) ; + } + /* + * Actually, srcA and srcB are column-major order matrixes, while they + * use row-major multiplication. Then above result equals to (B * A) likes these: + + for (i=0; i<4; i++){ + tmp.m[0][i] = (srcB->m[0][i] * srcA->m[0][0]) + + (srcB->m[1][i] * srcA->m[0][1]) + + (srcB->m[2][i] * srcA->m[0][2]) + + (srcB->m[3][i] * srcA->m[0][3]) ; + + tmp.m[1][i] = (srcB->m[0][i] * srcA->m[1][0]) + + (srcB->m[1][i] * srcA->m[1][1]) + + (srcB->m[2][i] * srcA->m[1][2]) + + (srcB->m[3][i] * srcA->m[1][3]) ; + + tmp.m[2][i] = (srcB->m[0][i] * srcA->m[2][0]) + + (srcB->m[1][i] * srcA->m[2][1]) + + (srcB->m[2][i] * srcA->m[2][2]) + + (srcB->m[3][i] * srcA->m[2][3]) ; + + tmp.m[3][i] = (srcB->m[0][i] * srcA->m[3][0]) + + (srcB->m[1][i] * srcA->m[3][1]) + + (srcB->m[2][i] * srcA->m[3][2]) + + (srcB->m[3][i] * srcA->m[3][3]) ; + } + + * So, it works. (Refer to math method of Homogeneous Coordinate) + */ + memcpy(result, &tmp, sizeof(ESMatrix)); +} + +void esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat sinAngle, cosAngle; + GLfloat mag = sqrtf(x * x + y * y + z * z); + + sinAngle = sinf ( angle * M_PI / 180.0f ); + cosAngle = cosf ( angle * M_PI / 180.0f ); + if ( mag > 0.0f ) + { + GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs; + GLfloat oneMinusCos; + ESMatrix rotMat; + + x /= mag; + y /= mag; + z /= mag; + + xx = x * x; + yy = y * y; + zz = z * z; + xy = x * y; + yz = y * z; + zx = z * x; + xs = x * sinAngle; + ys = y * sinAngle; + zs = z * sinAngle; + oneMinusCos = 1.0f - cosAngle; + + // Note: matrixes in OpenGL ES are stored in column-major order! + + rotMat[0][0] = (oneMinusCos * xx) + cosAngle; + rotMat[1][0] = (oneMinusCos * xy) - zs; + rotMat[2][0] = (oneMinusCos * zx) + ys; + rotMat[3][0] = 0.0F; + + rotMat[0][1] = (oneMinusCos * xy) + zs; + rotMat[1][1] = (oneMinusCos * yy) + cosAngle; + rotMat[2][1] = (oneMinusCos * yz) - xs; + rotMat[3][1] = 0.0F; + + rotMat[0][2] = (oneMinusCos * zx) - ys; + rotMat[1][2] = (oneMinusCos * yz) + xs; + rotMat[2][2] = (oneMinusCos * zz) + cosAngle; + rotMat[3][2] = 0.0F; + + rotMat[0][3] = 0.0F; + rotMat[1][3] = 0.0F; + rotMat[2][3] = 0.0F; + rotMat[3][3] = 1.0F; + + esMatrixMultiply( result, &rotMat, result ); + } +} + +void esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ) +{ + float deltaX = right - left; + float deltaY = top - bottom; + float deltaZ = farZ - nearZ; + ESMatrix ortho; + + if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) ) + return; + + esMatrixLoadIdentity(&ortho); + ortho[0][0] = 2.0f / deltaX; + ortho[3][0] = -(right + left) / deltaX; + ortho[1][1] = 2.0f / deltaY; + ortho[3][1] = -(top + bottom) / deltaY; + ortho[2][2] = -2.0f / deltaZ; + ortho[3][2] = -(nearZ + farZ) / deltaZ; + + esMatrixMultiply(result, &ortho, result); +} + + +JQuad::JQuad(JTexture *tex, float x, float y, float width, float height) + :mTex(tex), mX(x), mY(y), mWidth(width), mHeight(height) +{ + JASSERT(tex != NULL); + JRenderer::GetInstance()->TransferTextureToGLContext(*tex); + + mHotSpotX = 0.0f; + mHotSpotY = 0.0f; + //mBlend = BLEND_DEFAULT; + for (int i=0;i<4;i++) + mColor[i].color = 0xFFFFFFFF; + + mHFlipped = false; + mVFlipped = false; + + SetTextureRect(x, y, width, height); +} + +void JQuad::SetTextureRect(float x, float y, float w, float h) +{ + mX = x; + mY = y; + mWidth = w; + mHeight = h; + + mTX0 = x/mTex->mTexWidth; + mTY0 = y/mTex->mTexHeight; + mTX1 = (x+w)/mTex->mTexWidth; + mTY1 = (y+h)/mTex->mTexHeight; +} + + +void JQuad::GetTextureRect(float *x, float *y, float *w, float *h) +{ + *x=mX; *y=mY; *w=mWidth; *h=mHeight; +} + + +void JQuad::SetColor(PIXEL_TYPE color) +{ + for (int i=0;i<4;i++) + mColor[i].color = color; +} + + + +void JQuad::SetHotSpot(float x, float y) +{ + mHotSpotX = x; + mHotSpotY = y; +} + +JRenderer* JRenderer::mInstance = NULL; +BasicSprites::SpriteBatch^ mspriteBatchInstance; +bool JRenderer::m3DEnabled = false; + +////////////////////////////////////////////////////////////////////////// + +JTexture::JTexture() : mBuffer(NULL) +{ + mTexId = (ID3D11Texture2D*)-1; +} + +JTexture::~JTexture() +{ + if (mBuffer) + { + delete [] mBuffer; + mBuffer = NULL; + } + + mspriteBatchInstance->RemoveTexture(mTexId); +} + + +void JTexture::UpdateBits(int x, int y, int width, int height, PIXEL_TYPE* bits) +{ +} + +////////////////////////////////////////////////////////////////////////// + + +void JRenderer::Set3DFlag(bool flag) { m3DEnabled = flag; } + +JRenderer* JRenderer::GetInstance() +{ + if (mInstance == NULL) + { + mInstance = new JRenderer(); + mspriteBatchInstance = ref new SpriteBatch(); + + JASSERT(mInstance != NULL); + + mInstance->InitRenderer(); + } + + return mInstance; +} + + +void JRenderer::Destroy() +{ + if (mInstance) + { + mInstance->DestroyRenderer(); + delete mInstance; + mInstance = NULL; + mspriteBatchInstance = nullptr; + } +} + +JRenderer::JRenderer() + : + mLeft(0.0f), + mRight(SCREEN_WIDTH_F), + mTop(0.0f), + mBottom(SCREEN_HEIGHT_F), + mWindowWidth(0), + mWindowHeight(0), + m_Window(0) +{ +} + + +JRenderer::~JRenderer() +{ +} + + +void JRenderer::InitRenderer() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#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 Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + DX::ThrowIfFailed( + D3D11CreateDevice( + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + creationFlags, // Set set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &device, // Returns the Direct3D device created. + &m_featureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ) + ); + + // Get the Direct3D 11.1 API device and context interfaces. + DX::ThrowIfFailed( + device.As(&m_d3dDevice) + ); + + DX::ThrowIfFailed( + context.As(&m_d3dContext) + ); + + mspriteBatchInstance->Initialize( + m_d3dDevice.Get(), 10024 + ); +} + +void JRenderer::OnWindowsSizeChanged(void* window, float inWidth, float inHeight) +{ + if (mWindowWidth != inWidth || + mWindowHeight != inHeight +// || m_orientation != DisplayProperties::CurrentOrientation + ) + { + mWindowWidth = inWidth; + mWindowHeight = inHeight; + if(window != NULL) + m_Window = (IUnknown*)window; + + m_renderTargetView = nullptr; + m_depthStencilView = nullptr; + + if(m_swapChain != nullptr) + { + // If the swap chain already exists, resize it. + DX::ThrowIfFailed( + m_swapChain->ResizeBuffers( + 2, // Double-buffered swap chain. + static_cast(mWindowWidth), + static_cast(mWindowHeight), + DXGI_FORMAT_R8G8B8A8_UNORM, //DXGI_FORMAT_B8G8R8A8_UNORM, + 0 + ) + ); + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = 0; // Use automatic sizing. + swapChainDesc.Height = 0; + swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain 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 minimize latency. + swapChainDesc.Scaling = DXGI_SCALING_NONE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect. + swapChainDesc.Flags = 0; + + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + + ComPtr dxgiFactory; + DX::ThrowIfFailed( + dxgiAdapter->GetParent( + __uuidof(IDXGIFactory2), + &dxgiFactory + ) + ); + +// Windows::UI::Core::CoreWindow* window = (Windows::UI::Core::CoreWindow*)window.Get(); + DX::ThrowIfFailed( + dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_Window.Get(), + &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) + ); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + DX::ThrowIfFailed( + m_swapChain->GetBuffer( + 0, + __uuidof(ID3D11Texture2D), + &backBuffer + ) + ); + + 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); + + // Create a depth stencil view. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_D24_UNORM_S8_UINT, + backBufferDesc.Width, + backBufferDesc.Height, + 1, + 1, + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + DX::ThrowIfFailed( + m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + &depthStencil + ) + ); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed( + m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + &m_depthStencilView + ) + ); + + // Set the rendering viewport to target the entire window. + CD3D11_VIEWPORT viewport( + mLeft,// 0.0f, + mTop, //0.0f, + mRight, //static_cast(backBufferDesc.Width), + mBottom //static_cast(backBufferDesc.Height) + ); + + m_d3dContext->RSSetViewports(1, &viewport); + } +} + + +void JRenderer::DestroyRenderer() +{ +} + +void JRenderer::BeginScene() +{ + m_d3dContext->OMSetRenderTargets( + 1, + m_renderTargetView.GetAddressOf(), + nullptr + ); + + m_d3dContext->ClearRenderTargetView( + m_renderTargetView.Get(), + reinterpret_cast(&D2D1::ColorF(D2D1::ColorF::MidnightBlue)) + ); + + mspriteBatchInstance->Begin(); +} + + +void JRenderer::EndScene() +{ + + mspriteBatchInstance->End(); + + // The application may optionally specify "dirty" or "scroll" + // rects to improve efficiency in certain scenarios. + DXGI_PRESENT_PARAMETERS parameters = {0}; + parameters.DirtyRectsCount = 0; + parameters.pDirtyRects = nullptr; + parameters.pScrollRect = nullptr; + parameters.pScrollOffset = nullptr; + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present1(1, 0, ¶meters); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be entirely + // overwritten. If dirty or scroll rects are used, this call should be removed. + m_d3dContext->DiscardView(m_renderTargetView.Get()); + + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(m_depthStencilView.Get()); + + // If the device was removed either by a disconnect or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED) + { + // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources. + float width = mWindowWidth; + float height = mWindowHeight; + + mWindowWidth = 0; + mWindowHeight = 0; + m_swapChain = nullptr; + + InitRenderer(); + OnWindowsSizeChanged(NULL, width, height); + } + else + { + DX::ThrowIfFailed(hr); + } +} + +void JRenderer::BindTexture(JTexture *tex) +{ +} + + +void JRenderer::EnableTextureFilter(bool flag) +{ + if (flag) + mCurrentTextureFilter = TEX_FILTER_LINEAR; + else + mCurrentTextureFilter = TEX_FILTER_NEAREST; +} + +void Swap(float *a, float *b) +{ + float n=*a; + *a = *b; + *b = n; +} + +void JRenderer::RenderQuad(JQuad* quad, float xo, float yo, float angle, float xScale, float yScale) +{ + float width = quad->mWidth; + float height = quad->mHeight; + float x = -quad->mHotSpotX; + float y = quad->mHotSpotY; + + mspriteBatchInstance->Draw( + quad->mTex->mTexId, + float2( +// ((xo+((width*xScale)/2))*GetActualWidth())/SCREEN_WIDTH_F, +// ((yo+((height*yScale)/2))*GetActualHeight())/SCREEN_HEIGHT_F), + ((xo)*GetActualWidth())/SCREEN_WIDTH_F, + ((yo)*GetActualHeight())/SCREEN_HEIGHT_F), + PositionUnits::Pixels, + float2( + (width*xScale*GetActualWidth())/SCREEN_WIDTH_F, + (height*yScale*GetActualHeight())/SCREEN_HEIGHT_F + ), + SizeUnits::Pixels, + float4( + quad->mColor[0].r/255.0f, + quad->mColor[0].g/255.0f, + quad->mColor[0].b/255.0f, + quad->mColor[0].a/255.0f), + -angle, + BlendMode::Alpha, + float4(quad->mTX0, quad->mTX1, quad->mTY0, quad->mTY1), + Vector4(quad->mColor[0].color, quad->mColor[1].color, quad->mColor[2].color, quad->mColor[3].color) + ); +} + + +void JRenderer::RenderQuad(JQuad* quad, VertexColor* pt) +{ + float width = quad->mWidth; + float height = quad->mHeight; + float x = -quad->mHotSpotX; + float y = quad->mHotSpotY; + + mspriteBatchInstance->Draw( + quad->mTex->mTexId, + float2( + ((pt[0].x)*GetActualWidth())/SCREEN_WIDTH_F, + ((pt[0].y)*GetActualHeight())/SCREEN_HEIGHT_F), + PositionUnits::Pixels, + float2( + (width*GetActualWidth())/SCREEN_WIDTH_F, + (height*GetActualHeight())/SCREEN_HEIGHT_F + ), + SizeUnits::Pixels, + float4( + quad->mColor[0].r/255.0f, + quad->mColor[0].g/255.0f, + quad->mColor[0].b/255.0f, + quad->mColor[0].a/255.0f), + 0, + BlendMode::Alpha, + float4(quad->mTX0, quad->mTX1, quad->mTY0, quad->mTY1), + Vector4(pt[0].color, pt[1].color, pt[2].color, pt[3].color) + ); +} + + +void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE color) +{ + +} + + +void JRenderer::DrawRect(float x, float y, float width, float height, PIXEL_TYPE color) +{ +} + + +void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE* colors) +{ + JColor col[4]; + for (int i=0;i<4;i++) + col[i].color = colors[i]; + + FillRect(x, y, width, height, col); +} + +void JRenderer::FillRect(float x, float y, float width, float height, JColor* colors) +{ +} + + +void JRenderer::DrawLine(float x1, float y1, float x2, float y2, PIXEL_TYPE color) +{ + +} + + +void JRenderer::PlotArray(float *x, float *y, int count, PIXEL_TYPE color) +{ + +} + + + +void JRenderer::ScreenShot(const char* filename __attribute__((unused))) +{ + +} + + +static int getNextPower2(int width) +{ + int b = width; + int n; + for (n = 0; b != 0; n++) b >>= 1; + b = 1 << n; + if (b == 2 * width) b >>= 1; + return b; +} + + +static void jpg_null(j_decompress_ptr cinfo __attribute__((unused))) +{ +} + + +static boolean jpg_fill_input_buffer(j_decompress_ptr cinfo __attribute__((unused))) +{ + //// ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n"); + return 1; +} + +static void jpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + + cinfo->src->next_input_byte += (size_t) num_bytes; + cinfo->src->bytes_in_buffer -= (size_t) num_bytes; + + //// if (cinfo->src->bytes_in_buffer < 0) + //// ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n"); +} + +static void jpeg_mem_src(j_decompress_ptr cinfo, byte *mem, int len) +{ + cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr)); + cinfo->src->init_source = jpg_null; + cinfo->src->fill_input_buffer = jpg_fill_input_buffer; + cinfo->src->skip_input_data = jpg_skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; + cinfo->src->term_source = jpg_null; + cinfo->src->bytes_in_buffer = len; + cinfo->src->next_input_byte = mem; +} + +/* +============== +LoadJPG +============== +*/ +void JRenderer::LoadJPG(TextureInfo &textureInfo, const char *filename, int mode __attribute__((unused)), int TextureFormat __attribute__((unused))) +{ + textureInfo.mBits = NULL; + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + BYTE *rawdata, *rgbadata, *scanline, *p, *q; + int rawsize, i; + + JFileSystem* fileSystem = JFileSystem::GetInstance(); + if (!fileSystem->OpenFile(filename)) return; + + rawsize = fileSystem->GetFileSize(); + + rawdata = new BYTE[rawsize]; + + if (!rawdata) + { + fileSystem->CloseFile(); + return; + } + + fileSystem->ReadFile(rawdata, rawsize); + fileSystem->CloseFile(); + + // Initialize libJpeg Object + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, rawdata, rawsize); + + // Process JPEG header + jpeg_read_header(&cinfo, true); + + + + // Start Decompression + jpeg_start_decompress(&cinfo); + + // Check Colour Components + if(cinfo.output_components != 3 && cinfo.output_components != 4) + { + //// ri.Con_Printf(PRINT_ALL, "Invalid JPEG colour components\n"); + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + return; + } + + int tw = getNextPower2(cinfo.output_width); + int th = getNextPower2(cinfo.output_height); + + + // Allocate Memory for decompressed image + rgbadata = new BYTE[tw * th * 4]; + if(!rgbadata) + { + //// ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG buffer\n"); + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + delete [] rgbadata; + return; + } + + + // Pass sizes to output + + // Allocate Scanline buffer + scanline = (byte *)malloc(cinfo.output_width * 3); + if(!scanline) + { + //// ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG scanline buffer\n"); + + jpeg_destroy_decompress(&cinfo); + //// ri.FS_FreeFile(rawdata); + + delete [] rgbadata; + return; + } + + // Read Scanlines, and expand from RGB to RGBA + BYTE* currRow = rgbadata; + + while(cinfo.output_scanline < cinfo.output_height) + { + p = scanline; + jpeg_read_scanlines(&cinfo, &scanline, 1); + + q = currRow; + for(i=0; i<(int)cinfo.output_width; i++) + { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + q[3] = 255; + + p+=3; q+=4; + } + currRow += tw*4; + } + + // Free the scanline buffer + free(scanline); + + textureInfo.mBits = rgbadata; + textureInfo.mWidth = cinfo.output_width; + textureInfo.mHeight = cinfo.output_height; + textureInfo.mTexWidth = tw; + textureInfo.mTexHeight = th; + + // Finish Decompression + try { + jpeg_finish_decompress(&cinfo); + } catch(...) {} + + // Destroy JPEG object + jpeg_destroy_decompress(&cinfo); + + delete[] rawdata; +} + + +static void PNGCustomWarningFn(png_structp png_ptr __attribute__((unused)), png_const_charp warning_msg __attribute__((unused))) +{ + // ignore PNG warnings +} + + +static void PNGCustomReadDataFn(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + JFileSystem *fileSystem = (JFileSystem*)png_ptr->io_ptr; + + check = fileSystem->ReadFile(data, length); + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} + +JTexture* JRenderer::LoadTexture(const char* filename, int mode, int TextureFormat __attribute__((unused))) +{ + TextureInfo textureInfo; + + textureInfo.mBits = NULL; + + if (strstr(filename, ".jpg")!=NULL || strstr(filename, ".JPG")!=NULL) + LoadJPG(textureInfo, filename); +#if (!defined IOS) && (!defined QT_CONFIG) && (!defined SDL_CONFIG) && (!defined WP8) + else if(strstr(filename, ".gif")!=NULL || strstr(filename, ".GIF")!=NULL) + LoadGIF(textureInfo,filename); +#endif + else if(strstr(filename, ".png")!=NULL || strstr(filename, ".PNG")!=NULL) + LoadPNG(textureInfo, filename); + + if (textureInfo.mBits == NULL) { + printf("Texture %s failed to load\n", filename); + return NULL; + } + + bool ret = false; + + JTexture *tex = new JTexture(); + + if (tex) + { + if (mImageFilter != NULL) + mImageFilter->ProcessImage((PIXEL_TYPE*)textureInfo.mBits, textureInfo.mWidth, textureInfo.mHeight); + + tex->mFilter = TEX_FILTER_LINEAR; + tex->mWidth = textureInfo.mWidth; + tex->mHeight = textureInfo.mHeight; + tex->mTexWidth = textureInfo.mTexWidth; + tex->mTexHeight = textureInfo.mTexHeight; + + tex->mBuffer = textureInfo.mBits; + } + + return tex; +} + +int JRenderer::LoadPNG(TextureInfo &textureInfo, const char *filename, int mode __attribute__((unused)), int TextureFormat __attribute__((unused))) +{ + textureInfo.mBits = NULL; + + DWORD* p32; + + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height, tw, th; + int bit_depth, color_type, interlace_type, x, y; + DWORD* line; + + JFileSystem* fileSystem = JFileSystem::GetInstance(); + if (!fileSystem->OpenFile(filename)) + return JGE_ERR_CANT_OPEN_FILE; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + { + fileSystem->CloseFile(); + + return JGE_ERR_PNG; + } + + png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, PNGCustomWarningFn); + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + //fclose(fp); + fileSystem->CloseFile(); + + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + + return JGE_ERR_PNG; + } + png_init_io(png_ptr, NULL); + png_set_read_fn(png_ptr, (png_voidp)fileSystem, PNGCustomReadDataFn); + + png_set_sig_bytes(png_ptr, sig_read); + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); + png_set_strip_16(png_ptr); + png_set_packing(png_ptr); + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + line = (DWORD*) malloc(width * 4); + if (!line) + { + //fclose(fp); + fileSystem->CloseFile(); + + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + return JGE_ERR_MALLOC_FAILED; + } + + + tw = getNextPower2(width); + th = getNextPower2(height); + + int size = tw * th * 4; // RGBA + + BYTE* buffer = new BYTE[size]; + + //JTexture *tex = new JTexture(); + + if (buffer) + { + + + p32 = (DWORD*) buffer; + + for (y = 0; y < (int)height; y++) + { + png_read_row(png_ptr, (BYTE*) line, png_bytep_NULL); + for (x = 0; x < (int)width; x++) + { + DWORD color32 = line[x]; + int a = (color32 >> 24) & 0xff; + int r = color32 & 0xff; + int g = (color32 >> 8) & 0xff; + int b = (color32 >> 16) & 0xff; + + color32 = r | (g << 8) | (b << 16) | (a << 24); + *(p32+x) = color32; + + } + p32 += tw; + + } + + } + + + free (line); + + png_read_end(png_ptr, info_ptr); + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + fileSystem->CloseFile(); + + + textureInfo.mBits = buffer; + textureInfo.mWidth = width; + textureInfo.mHeight = height; + textureInfo.mTexWidth = tw; + textureInfo.mTexHeight = th; + + return 1; + //return textureInfo; + +} + + +void JRenderer::TransferTextureToGLContext(JTexture& inTexture) +{ + if (inTexture.mBuffer != NULL) + { + D3D11_TEXTURE2D_DESC desc; + HRESULT hr = E_FAIL; + + desc.Width = static_cast( inTexture.mTexWidth ); + desc.Height = static_cast( inTexture.mTexHeight ); + desc.MipLevels = static_cast( 1 ); + desc.ArraySize = static_cast( 1 ); + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = inTexture.mBuffer; + initData.SysMemPitch = inTexture.mTexWidth*4; + initData.SysMemSlicePitch = inTexture.mTexHeight*inTexture.mTexWidth*4; + + ID3D11Texture2D* tex2D = nullptr; + hr = m_d3dDevice->CreateTexture2D( &desc, &initData, &inTexture.mTexId); + if( S_OK != hr) + return; + + mspriteBatchInstance->AddTexture(inTexture.mTexId); + + delete [] inTexture.mBuffer; + inTexture.mBuffer = NULL; + } +} + +JTexture* JRenderer::CreateTexture(int width, int height, int mode __attribute__((unused))) +{ + JTexture *tex = new JTexture(); + HRESULT hr = E_FAIL; + + if (tex) + { + int size = width * height * sizeof(PIXEL_TYPE); // RGBA + BYTE* buffer = new BYTE[size]; + if (buffer) + { + tex->mFilter = TEX_FILTER_LINEAR; + tex->mWidth = width; + tex->mHeight = height; + tex->mTexWidth = width; + tex->mTexHeight = height; + tex->mBuffer = buffer; + + TransferTextureToGLContext(*tex); + } + else + { + delete tex; + tex = NULL; + } + } + + return tex; +} + + +void JRenderer::EnableVSync(bool flag __attribute__((unused))) +{ + // if (flag) + // hge->System_SetState(HGE_FPS, 60); // HGEFPS_VSYNC + // else + // hge->System_SetState(HGE_FPS, HGEFPS_UNLIMITED); +} + + +void JRenderer::ClearScreen(PIXEL_TYPE color) +{ + JColor col; + col.color = color; + FLOAT colorf[4]; + colorf[0] = col.r/255.0f; + colorf[1] = col.g/255.0f; + colorf[2] = col.b/255.0f; + colorf[3] = col.a/255.0f; + + m_d3dContext->ClearRenderTargetView( + m_renderTargetView.Get(), colorf + ); +} + + +void JRenderer::SetTexBlend(int src, int dest) +{ + +} + + +void JRenderer::SetTexBlendSrc(int src) +{// NOT USED + +} + + +void JRenderer::SetTexBlendDest(int dest) +{// NOT USED + +} + + +void JRenderer::Enable2D() +{// NOT USED + if (mCurrentRenderMode == MODE_2D) + return; + + mCurrentRenderMode = MODE_2D; + + +} + + +void JRenderer::Enable3D() +{ /* NOT USED */ +} + + +void JRenderer::SetClip(int, int, int, int) +{// NOT USED +} + +void JRenderer::LoadIdentity() +{// NOT USED +} + +void JRenderer::Translate(float, float, float) +{// NOT USED +} + +void JRenderer::RotateX(float) +{// NOT USED +} + +void JRenderer::RotateY(float) +{// NOT USED +} + +void JRenderer::RotateZ(float) +{// NOT USED +} + + +void JRenderer::PushMatrix() +{// NOT USED +} + +void JRenderer::PopMatrix() +{// NOT USED +} + +void JRenderer::RenderTriangles(JTexture* texture, Vertex3D *vertices, int start, int count) +{// NOT USED + +} + + +void JRenderer::SetFOV(float fov) +{// NOT USED + mFOV = fov; +} + + +void JRenderer::FillPolygon(float* x, float* y, int count, PIXEL_TYPE color) +{// NOT USED + +} + + +void JRenderer::DrawPolygon(float* x, float* y, int count, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::DrawLine(float x1, float y1, float x2, float y2, float lineWidth, PIXEL_TYPE color) +{// NOT USED + float dy=y2-y1; + float dx=x2-x1; + if(dy==0 && dx==0) + return; + + float l=(float)hypot(dx,dy); + + float x[4]; + float y[4]; + + x[0]=x1+lineWidth*(y2-y1)/l; + y[0]=y1-lineWidth*(x2-x1)/l; + + x[1]=x1-lineWidth*(y2-y1)/l; + y[1]=y1+lineWidth*(x2-x1)/l; + + x[2]=x2-lineWidth*(y2-y1)/l; + y[2]=y2+lineWidth*(x2-x1)/l; + + x[3]=x2+lineWidth*(y2-y1)/l; + y[3]=y2-lineWidth*(x2-x1)/l; + + FillPolygon(x, y, 4, color); +} + + +void JRenderer::DrawCircle(float x, float y, float radius, PIXEL_TYPE color) +{// NOT USED +} + +void JRenderer::FillCircle(float x, float y, float radius, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::DrawPolygon(float x, float y, float size, int count, float startingAngle, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::FillPolygon(float x, float y, float size, int count, float startingAngle, PIXEL_TYPE color) +{// NOT USED +} + + +void JRenderer::SetImageFilter(JImageFilter* imageFilter) +{ + mImageFilter = imageFilter; +} + + + +void JRenderer::DrawRoundRect(float x, float y, float w, float h, float radius, PIXEL_TYPE color) +{// NOT USED +} + + + +void JRenderer::FillRoundRect(float x, float y, float w, float h, float radius, PIXEL_TYPE color) +{// NOT USED +} + diff --git a/JGE/src/DirectX/JSfx.cpp b/JGE/src/DirectX/JSfx.cpp new file mode 100644 index 000000000..1cef77dc7 --- /dev/null +++ b/JGE/src/DirectX/JSfx.cpp @@ -0,0 +1,153 @@ +//------------------------------------------------------------------------------------- +// +// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows. +// +// Licensed under the BSD license, see LICENSE in JGE root for details. +// +// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) +// +//------------------------------------------------------------------------------------- +#include "DebugRoutines.h" +#include "../../include/JSoundSystem.h" +#include "../../include/JFileSystem.h" + +////////////////////////////////////////////////////////////////////////// +JMusic::JMusic() +{ +} + +void JMusic::Update(){ + +} + +int JMusic::getPlayTime(){ + return 0; +} + +JMusic::~JMusic() +{ +} + +////////////////////////////////////////////////////////////////////////// +JSample::JSample() +{ + +} + +JSample::~JSample() +{ +} + +unsigned long JSample::fileSize() +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////// +JSoundSystem* JSoundSystem::mInstance = NULL; + +JSoundSystem* JSoundSystem::GetInstance() +{ + if (mInstance == NULL) + { + mInstance = new JSoundSystem(); + mInstance->InitSoundSystem(); + } + return mInstance; +} + + +void JSoundSystem::Destroy() +{ + if (mInstance) + { + mInstance->DestroySoundSystem(); + delete mInstance; + mInstance = NULL; + } +} + + +JSoundSystem::JSoundSystem() +{ + mVolume = 0; + mSampleVolume = 0; +} + +JSoundSystem::~JSoundSystem() +{ +} + +void JSoundSystem::InitSoundSystem() +{ +} + + +void JSoundSystem::DestroySoundSystem() +{ +} + + +JMusic *JSoundSystem::LoadMusic(const char *fileName) +{ + cerr << fileName << endl; + return NULL; +} + + +void JSoundSystem::PlayMusic(JMusic *music, bool looping) +{ + music = 0; + looping = false; +} + + +void JSoundSystem::StopMusic(JMusic *music) +{ + music = 0; +} + + +void JSoundSystem::PauseMusic(JMusic *music) +{ + StopMusic(music); +} + + +void JSoundSystem::ResumeMusic(JMusic *music) +{ + PlayMusic(music); +} + + +void JSoundSystem::SetVolume(int volume) +{ + SetMusicVolume(volume); + SetSfxVolume(volume); +} + +void JSoundSystem::SetMusicVolume(int volume) +{ + mVolume = volume; +} + +void JSoundSystem::SetSfxVolume(int volume) +{ + //this sets the volume to all channels then reverts back the volume for music.. + //that's a bit dirty but it works + mSampleVolume = volume; + SetMusicVolume(mVolume); +} + +JSample *JSoundSystem::LoadSample(const char *fileName) +{ + cerr << fileName << endl; + return NULL; +} + + +void JSoundSystem::PlaySample(JSample *sample) +{ + sample = 0; +} + diff --git a/projects/mtg/wagic-SDL.pro b/projects/mtg/wagic-SDL.pro index aec343ad8..d6622e23d 100644 --- a/projects/mtg/wagic-SDL.pro +++ b/projects/mtg/wagic-SDL.pro @@ -77,7 +77,6 @@ windows{ ../../JGE/Dependencies/libjpeg/jquant2.c \ ../../JGE/Dependencies/libjpeg/jutils.c - DEFINES += SDL_ATOMIC_DISABLED SOURCES += \ ../../JGE/Dependencies/SDL/src/core/windows/SDL_windows.c\ diff --git a/projects/mtg/wagic.vcxproj b/projects/mtg/wagic.vcxproj new file mode 100644 index 000000000..94ef3dd5a --- /dev/null +++ b/projects/mtg/wagic.vcxproj @@ -0,0 +1,777 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {c724e4d7-a1d1-41be-8f22-382c6cb3cdac} + Win32Proj + wagic + wagic + en-US + 11.0 + true + + + + StaticLibrary + true + v110 + + + StaticLibrary + true + v110 + + + StaticLibrary + true + v110 + + + StaticLibrary + false + true + v110 + + + StaticLibrary + false + true + v110 + + + StaticLibrary + false + true + v110 + + + + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)$(Configuration)\ + + + false + $(SolutionDir)$(Configuration)\ + + + false + + + false + + + false + + + false + + + + Use + false + true + include;../../JGE/include;../../JGE/src/zipFS;../../JGE/Dependencies/zlib;../../JGE/Dependencies/libpng;../../JGE/Dependencies/libjpeg;extra;%(AdditionalIncludeDirectories) + TIXML_USE_STL;WP8;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + include;../../JGE/include;../../JGE/src/zipFS;../../JGE/Dependencies/zlib;../../JGE/Dependencies/libpng;../../JGE/Dependencies/libjpeg;extra;%(AdditionalIncludeDirectories) + TIXML_USE_STL;WP8;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + NotUsing + NotUsing + + + + + + \ No newline at end of file