Added the ASSIMP library
Added the files provided for the tutorial Added the SplitMeshNode and SubMeshNode classes
@ -22,8 +22,8 @@ DirectXFramework::DirectXFramework(unsigned int width, unsigned int height) : Fr
|
||||
|
||||
// Initialise vectors used to create camera. We will move these
|
||||
// to a separate Camera class later
|
||||
_eyePosition = XMFLOAT4(0.0f, 1.0f, -15.0f, 0.0f);
|
||||
_focalPointPosition = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
_eyePosition = XMFLOAT4(0.0f, 20.0f, -90.0f, 0.0f);
|
||||
_focalPointPosition = XMFLOAT4(0.0f, 20.0f, 0.0f, 0.0f);
|
||||
_upVector = XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ bool DirectXFramework::Initialise()
|
||||
// Create camera and projection matrices (we will look at how the
|
||||
// camera matrix is created from vectors later)
|
||||
XMStoreFloat4x4(&_projectionTransformation, XMMatrixPerspectiveFovLH(XM_PIDIV4, (float)GetWindowWidth() / GetWindowHeight(), 1.0f, 10000.0f));
|
||||
_resourceManager = make_shared<ResourceManager>();
|
||||
_sceneGraph = make_shared<SceneGraph>();
|
||||
CreateSceneGraph();
|
||||
return _sceneGraph->Initialise();
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <vector>
|
||||
#include "Framework.h"
|
||||
#include "DirectXCore.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SceneGraph.h"
|
||||
|
||||
class DirectXFramework : public Framework
|
||||
@ -25,6 +26,8 @@ public:
|
||||
inline ComPtr<ID3D11Device> GetDevice() { return _device; }
|
||||
inline ComPtr<ID3D11DeviceContext> GetDeviceContext() { return _deviceContext; }
|
||||
|
||||
inline shared_ptr<ResourceManager> GetResourceManager() { return _resourceManager; }
|
||||
|
||||
XMMATRIX GetViewTransformation();
|
||||
XMMATRIX GetProjectionTransformation();
|
||||
|
||||
@ -59,5 +62,7 @@ private:
|
||||
float _backgroundColour[4];
|
||||
|
||||
bool GetDeviceAndSwapChain();
|
||||
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
};
|
||||
|
||||
|
@ -7,12 +7,39 @@ void Graphics2::CreateSceneGraph()
|
||||
SceneGraphPointer sceneGraph = GetSceneGraph();
|
||||
|
||||
// This is where you add nodes to the scene graph
|
||||
//shared_ptr<TexturedCubeNode> cube = make_shared<TexturedCubeNode>(L"Body", L"Textures\\woodbox.bmp");
|
||||
//cube->SetWorldTransform(XMMatrixScaling(5.0f, 8.0f, 2.5f) * XMMatrixTranslation(0, 23.0f, 0));
|
||||
//sceneGraph->Add(cube);
|
||||
|
||||
shared_ptr<SplitMeshNode> node = make_shared<SplitMeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||
node->SetWorldTransform(XMMatrixScaling(0.5f, 0.5f, 0.5f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 90.0f * XM_PI / 180.0f) * XMMatrixTranslation(-30.0f, 20.0f, 0));
|
||||
sceneGraph->Add(node);
|
||||
|
||||
SetBackgroundColour(XMFLOAT4(0.29f, 0.38f, 0.72f, 1.0f));
|
||||
|
||||
_currentRotation = 0;
|
||||
_currentSideRotation = 0;
|
||||
_currentPropRotation = 0;
|
||||
}
|
||||
|
||||
void Graphics2::UpdateSceneGraph()
|
||||
{
|
||||
SceneGraphPointer sceneGraph = GetSceneGraph();
|
||||
|
||||
// This is where you make any changes to the local world transformations to nodes
|
||||
// in the scene graph
|
||||
sceneGraph->SetWorldTransform((SharedMethods::RotateFromPoint(30.0f, -20.0f, 0, XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, -1.0f, 0.0f), _currentSideRotation * XM_PI / 180.0f))) * XMMatrixRotationAxis(XMVectorSet(0.0f, -1.0f, 0.0f, 0.0f), _currentRotation * XM_PI / 180.0f));
|
||||
|
||||
sceneGraph->Find(L"airscrew")->SetWorldTransform(SharedMethods::RotateFromPoint(0.0f, 15.471f, 14.5f, XMMatrixRotationAxis(XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), _currentPropRotation * XM_PI / 180.0f)));
|
||||
|
||||
if (_currentRotation == 360)
|
||||
{
|
||||
_currentRotation = 0;
|
||||
//_currentSideRotation = 0;
|
||||
_currentPropRotation = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentRotation += 1;
|
||||
_currentSideRotation += 0.3;
|
||||
_currentPropRotation += 100;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include "SharedMethods.h"
|
||||
#include "TexturedCubeNode.h"
|
||||
#include "MeshNode.h"
|
||||
#include "SplitMeshNode.h"
|
||||
#include <ctime>
|
||||
|
||||
class Graphics2 : public DirectXFramework
|
||||
{
|
||||
@ -7,5 +12,9 @@ public:
|
||||
void CreateSceneGraph();
|
||||
void UpdateSceneGraph();
|
||||
|
||||
private:
|
||||
float _currentRotation = 0.0f;
|
||||
float _currentSideRotation = 0.0f;
|
||||
float _currentPropRotation = 0.0f;
|
||||
};
|
||||
|
||||
|
@ -75,6 +75,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>..\Assimp\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@ -149,10 +150,21 @@
|
||||
<ClInclude Include="DirectXFramework.h" />
|
||||
<ClInclude Include="Graphics2.h" />
|
||||
<ClInclude Include="HelperFunctions.h" />
|
||||
<ClInclude Include="Mesh.h" />
|
||||
<ClInclude Include="MeshNode.h" />
|
||||
<ClInclude Include="MeshRenderer.h" />
|
||||
<ClInclude Include="Renderer.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="ResourceManager.h" />
|
||||
<ClInclude Include="SceneGraph.h" />
|
||||
<ClInclude Include="SceneNode.h" />
|
||||
<ClInclude Include="SharedMethods.h" />
|
||||
<ClInclude Include="SplitMeshNode.h" />
|
||||
<ClInclude Include="SubMeshNode.h" />
|
||||
<ClInclude Include="SubMeshRenderer.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="TexturedCubeNode.h" />
|
||||
<ClInclude Include="WICTextureLoader.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Graphics2.rc" />
|
||||
@ -160,11 +172,41 @@
|
||||
<ItemGroup>
|
||||
<Image Include="Graphics2.ico" />
|
||||
<Image Include="small.ico" />
|
||||
<Image Include="Textures\Bricks.png" />
|
||||
<Image Include="Textures\Concrete.png" />
|
||||
<Image Include="Textures\white.png" />
|
||||
<Image Include="Textures\Wood.png" />
|
||||
<Image Include="Textures\woodbox.bmp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Framework.cpp" />
|
||||
<ClCompile Include="DirectXFramework.cpp" />
|
||||
<ClCompile Include="Graphics2.cpp" />
|
||||
<ClCompile Include="Mesh.cpp" />
|
||||
<ClCompile Include="MeshNode.cpp" />
|
||||
<ClCompile Include="MeshRenderer.cpp" />
|
||||
<ClCompile Include="ResourceManager.cpp" />
|
||||
<ClCompile Include="SceneGraph.cpp" />
|
||||
<ClCompile Include="SharedMethods.cpp" />
|
||||
<ClCompile Include="SplitMeshNode.cpp" />
|
||||
<ClCompile Include="SubMeshNode.cpp" />
|
||||
<ClCompile Include="SubMeshRenderer.cpp" />
|
||||
<ClCompile Include="TexturedCubeNode.cpp" />
|
||||
<ClCompile Include="WICTextureLoader.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="shader.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="TexturedShaders.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="assimp-vc140-mt.dll" />
|
||||
<None Include="zlib.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -13,6 +13,9 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Shaders">
|
||||
<UniqueIdentifier>{8d44fb5e-e3a8-497e-9825-b8031cb66d67}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="targetver.h">
|
||||
@ -45,6 +48,39 @@
|
||||
<ClInclude Include="SceneNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WICTextureLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TexturedCubeNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mesh.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MeshNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MeshRenderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Renderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ResourceManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SharedMethods.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SubMeshNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SubMeshRenderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SplitMeshNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Graphics2.rc">
|
||||
@ -58,6 +94,21 @@
|
||||
<Image Include="Graphics2.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Textures\Bricks.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Textures\Concrete.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Textures\white.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Textures\Wood.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="Textures\woodbox.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Framework.cpp">
|
||||
@ -69,5 +120,50 @@
|
||||
<ClCompile Include="Graphics2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SceneGraph.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WICTextureLoader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TexturedCubeNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mesh.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MeshNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MeshRenderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ResourceManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SharedMethods.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SubMeshNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SubMeshRenderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SplitMeshNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="shader.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</Text>
|
||||
<Text Include="TexturedShaders.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="assimp-vc140-mt.dll" />
|
||||
<None Include="zlib.dll" />
|
||||
</ItemGroup>
|
||||
</Project>
|
70
Graphics2/Mesh.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "Mesh.h"
|
||||
|
||||
// Material methods
|
||||
|
||||
Material::Material(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, ComPtr<ID3D11ShaderResourceView> texture )
|
||||
{
|
||||
_materialName = materialName;
|
||||
_diffuseColour = diffuseColour;
|
||||
_specularColour = specularColour;
|
||||
_shininess = shininess;
|
||||
_opacity = opacity;
|
||||
_texture = texture;
|
||||
}
|
||||
|
||||
Material::~Material(void)
|
||||
{
|
||||
}
|
||||
|
||||
// SubMesh methods
|
||||
|
||||
SubMesh::SubMesh(ComPtr<ID3D11Buffer> vertexBuffer,
|
||||
ComPtr<ID3D11Buffer> indexBuffer,
|
||||
size_t vertexCount,
|
||||
size_t indexCount,
|
||||
shared_ptr<Material> material)
|
||||
{
|
||||
_vertexBuffer = vertexBuffer;
|
||||
_indexBuffer = indexBuffer;
|
||||
_vertexCount = vertexCount;
|
||||
_indexCount = indexCount;
|
||||
_material = material;
|
||||
}
|
||||
|
||||
SubMesh::~SubMesh(void)
|
||||
{
|
||||
}
|
||||
|
||||
// Mesh methods
|
||||
|
||||
size_t Mesh::GetSubMeshCount()
|
||||
{
|
||||
return _subMeshList.size();
|
||||
}
|
||||
|
||||
shared_ptr<SubMesh> Mesh::GetSubMesh(unsigned int i)
|
||||
{
|
||||
if (i >= 0 && i < _subMeshList.size())
|
||||
{
|
||||
return _subMeshList[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::AddSubMesh(shared_ptr<SubMesh> subMesh)
|
||||
{
|
||||
_subMeshList.push_back(subMesh);
|
||||
}
|
||||
|
||||
shared_ptr<Node> Mesh::GetRootNode()
|
||||
{
|
||||
return _rootNode;
|
||||
}
|
||||
|
||||
void Mesh::SetRootNode(shared_ptr<Node> node)
|
||||
{
|
||||
_rootNode = node;
|
||||
}
|
92
Graphics2/Mesh.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
#include "core.h"
|
||||
#include "DirectXCore.h"
|
||||
#include <vector>
|
||||
|
||||
// Core material class. Ideally, this should be extended to include more material attributes that can be
|
||||
// recovered from Assimp, but this handles the basics.
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, ComPtr<ID3D11ShaderResourceView> texture );
|
||||
~Material();
|
||||
|
||||
inline wstring GetMaterialName() { return _materialName; }
|
||||
inline XMFLOAT4 GetDiffuseColour() { return _diffuseColour; }
|
||||
inline XMFLOAT4 GetSpecularColour() { return _specularColour; }
|
||||
inline float GetShininess() { return _shininess; }
|
||||
inline float GetOpacity() { return _opacity; }
|
||||
inline ComPtr<ID3D11ShaderResourceView> GetTexture() { return _texture; }
|
||||
|
||||
private:
|
||||
wstring _materialName;
|
||||
XMFLOAT4 _diffuseColour;
|
||||
XMFLOAT4 _specularColour;
|
||||
float _shininess;
|
||||
float _opacity;
|
||||
ComPtr<ID3D11ShaderResourceView> _texture;
|
||||
};
|
||||
|
||||
// Basic SubMesh class. A Mesh consists of one or more sub-meshes. The submesh provides everything that is needed to
|
||||
// draw the sub-mesh.
|
||||
|
||||
class SubMesh
|
||||
{
|
||||
public:
|
||||
SubMesh(ComPtr<ID3D11Buffer> vertexBuffer,
|
||||
ComPtr<ID3D11Buffer> indexBuffer,
|
||||
size_t vertexCount,
|
||||
size_t indexCount,
|
||||
shared_ptr<Material> material);
|
||||
~SubMesh();
|
||||
|
||||
inline ComPtr<ID3D11Buffer> GetVertexBuffer() { return _vertexBuffer; }
|
||||
inline ComPtr<ID3D11Buffer> GetIndexBuffer() { return _indexBuffer; }
|
||||
inline shared_ptr<Material> GetMaterial() { return _material; }
|
||||
inline size_t GetVertexCount() { return _vertexCount; }
|
||||
inline size_t GetIndexCount() { return _indexCount; }
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Buffer> _vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> _indexBuffer;
|
||||
shared_ptr<Material> _material;
|
||||
size_t _vertexCount;
|
||||
size_t _indexCount;
|
||||
};
|
||||
|
||||
// The core Mesh class. A Mesh corresponds to a scene in ASSIMP. A mesh consists of one or more sub-meshes.
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
inline void SetName(wstring name) { _name = name; }
|
||||
inline wstring GetName() { return _name; }
|
||||
inline size_t GetMeshCount() { return _meshIndices.size(); }
|
||||
inline unsigned int GetMesh(unsigned int index) { return _meshIndices[index]; }
|
||||
inline void AddMesh(unsigned int meshIndex) { _meshIndices.push_back(meshIndex); }
|
||||
inline size_t GetChildrenCount() { return _children.size(); }
|
||||
inline shared_ptr<Node> GetChild(unsigned int index) { return _children[index]; }
|
||||
inline void AddChild(shared_ptr<Node> node) { _children.push_back(node); }
|
||||
|
||||
private:
|
||||
wstring _name;
|
||||
vector<unsigned int> _meshIndices;
|
||||
vector<shared_ptr<Node>> _children;
|
||||
};
|
||||
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
size_t GetSubMeshCount();
|
||||
shared_ptr<SubMesh> GetSubMesh(unsigned int i);
|
||||
void AddSubMesh(shared_ptr<SubMesh> subMesh);
|
||||
shared_ptr<Node> GetRootNode();
|
||||
void SetRootNode(shared_ptr<Node> node);
|
||||
|
||||
private:
|
||||
vector<shared_ptr<SubMesh>> _subMeshList;
|
||||
shared_ptr<Node> _rootNode;
|
||||
};
|
||||
|
||||
|
29
Graphics2/MeshNode.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "MeshNode.h"
|
||||
|
||||
bool MeshNode::Initialise()
|
||||
{
|
||||
_resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager();
|
||||
_renderer = dynamic_pointer_cast<MeshRenderer>(_resourceManager->GetRenderer(L"PNT"));
|
||||
_mesh = _resourceManager->GetMesh(_modelName);
|
||||
if (_mesh == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _renderer->Initialise();
|
||||
}
|
||||
|
||||
void MeshNode::Shutdown()
|
||||
{
|
||||
_resourceManager->ReleaseMesh(_modelName);
|
||||
}
|
||||
|
||||
void MeshNode::Render()
|
||||
{
|
||||
_renderer->SetMesh(_mesh);
|
||||
_renderer->SetWorldTransformation(XMLoadFloat4x4(&_combinedWorldTransformation));
|
||||
_renderer->SetCameraPosition(XMFLOAT4(0.0f, 0.0f, -100.0f, 1.0f));
|
||||
_renderer->SetAmbientLight(XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
_renderer->SetDirectionalLight(XMVectorSet(0.0f, -1.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
_renderer->Render();
|
||||
}
|
||||
|
22
Graphics2/MeshNode.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "SceneNode.h"
|
||||
#include "DirectXFramework.h"
|
||||
#include "MeshRenderer.h"
|
||||
|
||||
class MeshNode : public SceneNode
|
||||
{
|
||||
public:
|
||||
MeshNode(wstring name, wstring modelName) : SceneNode(name) { _modelName = modelName; }
|
||||
|
||||
bool Initialise();
|
||||
void Render();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
shared_ptr<MeshRenderer> _renderer;
|
||||
|
||||
wstring _modelName;
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
shared_ptr<Mesh> _mesh;
|
||||
};
|
||||
|
234
Graphics2/MeshRenderer.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
#include "MeshRenderer.h"
|
||||
#include "DirectXFramework.h"
|
||||
|
||||
void MeshRenderer::SetMesh(shared_ptr<Mesh> mesh)
|
||||
{
|
||||
_mesh = mesh;
|
||||
}
|
||||
|
||||
void MeshRenderer::SetWorldTransformation(FXMMATRIX worldTransformation)
|
||||
{
|
||||
XMStoreFloat4x4(&_worldTransformation, worldTransformation);
|
||||
}
|
||||
|
||||
void MeshRenderer::SetAmbientLight(XMFLOAT4 ambientLight)
|
||||
{
|
||||
_ambientLight = ambientLight;
|
||||
}
|
||||
|
||||
void MeshRenderer::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour)
|
||||
{
|
||||
_directionalLightColour = lightColour;
|
||||
XMStoreFloat4(&_directionalLightVector, lightVector);
|
||||
}
|
||||
|
||||
void MeshRenderer::SetCameraPosition(XMFLOAT4 cameraPosition)
|
||||
{
|
||||
_cameraPosition = cameraPosition;
|
||||
}
|
||||
|
||||
bool MeshRenderer::Initialise()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
BuildShaders();
|
||||
BuildVertexLayout();
|
||||
BuildConstantBuffer();
|
||||
BuildBlendState();
|
||||
BuildRendererState();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshRenderer::RenderNode(shared_ptr<Node> node, bool renderTransparent)
|
||||
{
|
||||
unsigned int subMeshCount = (unsigned int)node->GetMeshCount();
|
||||
// Loop through all submeshes in the mesh, rendering them
|
||||
for (unsigned int i = 0; i < subMeshCount; i++)
|
||||
{
|
||||
unsigned int meshIndex = node->GetMesh(i);
|
||||
shared_ptr<SubMesh> subMesh = _mesh->GetSubMesh(meshIndex);
|
||||
shared_ptr<Material> material = subMesh->GetMaterial();
|
||||
float opacity = material->GetOpacity();
|
||||
if ((renderTransparent && opacity < 1.0f) ||
|
||||
(!renderTransparent && opacity == 1.0f))
|
||||
{
|
||||
UINT stride = sizeof(VERTEX);
|
||||
UINT offset = 0;
|
||||
_vertexBuffer = subMesh->GetVertexBuffer();
|
||||
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
|
||||
_indexBuffer = subMesh->GetIndexBuffer();
|
||||
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
|
||||
_cBuffer.DiffuseCoefficient = material->GetDiffuseColour();
|
||||
_cBuffer.SpecularCoefficient = material->GetSpecularColour();
|
||||
_cBuffer.Shininess = material->GetShininess();
|
||||
_cBuffer.Opacity = opacity;
|
||||
// Update the constant buffer
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &_cBuffer, 0, 0);
|
||||
_texture = material->GetTexture();
|
||||
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
|
||||
_deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
_deviceContext->DrawIndexed(static_cast<UINT>(subMesh->GetIndexCount()), 0, 0);
|
||||
}
|
||||
}
|
||||
// Render the children
|
||||
unsigned int childrenCount = (unsigned int)node->GetChildrenCount();
|
||||
// Loop through all submeshes in the mesh, rendering them
|
||||
for (unsigned int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
RenderNode(node->GetChild(i), renderTransparent);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshRenderer::Render()
|
||||
{
|
||||
// Turn off back face culling while we render a mesh.
|
||||
// We do this since ASSIMP does not appear to be setting the
|
||||
// TWOSIDED property on materials correctly. Without turning off
|
||||
// back face culling, some materials do not render correctly.
|
||||
_deviceContext->RSSetState(_noCullRasteriserState.Get());
|
||||
|
||||
XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation();
|
||||
XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetViewTransformation();
|
||||
|
||||
XMMATRIX completeTransformation = XMLoadFloat4x4(&_worldTransformation) * viewTransformation * projectionTransformation;
|
||||
|
||||
// Draw the first cube
|
||||
|
||||
_cBuffer.CompleteTransformation = completeTransformation;
|
||||
_cBuffer.WorldTransformation = XMLoadFloat4x4(&_worldTransformation);
|
||||
_cBuffer.AmbientColor = _ambientLight;
|
||||
_cBuffer.LightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector));
|
||||
_cBuffer.LightColor = _directionalLightColour;
|
||||
_cBuffer.CameraPosition = _cameraPosition;
|
||||
|
||||
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
|
||||
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
|
||||
_deviceContext->IASetInputLayout(_layout.Get());
|
||||
|
||||
// Set the blend state correctly to handle opacity
|
||||
float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
_deviceContext->OMSetBlendState(_transparentBlendState.Get(), blendFactors, 0xffffffff);
|
||||
|
||||
// We do two passes through the nodes. The first time we render nodes
|
||||
// that are not transparent (i.e. their opacity == 1.0f).
|
||||
RenderNode(_mesh->GetRootNode(), false);
|
||||
// Now we render any transparent nodes
|
||||
// We have to do this since blending always blends the submesh with
|
||||
// whatever is in the render target. If we render a transparent node
|
||||
// first, it will be opaque.
|
||||
RenderNode(_mesh->GetRootNode(), true);
|
||||
|
||||
// Turn back face culling back on in case another renderer
|
||||
// relies on it
|
||||
_deviceContext->RSSetState(_defaultRasteriserState.Get());
|
||||
}
|
||||
|
||||
void MeshRenderer::Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void MeshRenderer::BuildShaders()
|
||||
{
|
||||
DWORD shaderCompileFlags = 0;
|
||||
#if defined( _DEBUG )
|
||||
shaderCompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
ComPtr<ID3DBlob> compilationMessages = nullptr;
|
||||
|
||||
//Compile vertex shader
|
||||
HRESULT hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"VShader", "vs_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_vertexShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
// Even if there are no compiler messages, check to make sure there were no other errors.
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf()));
|
||||
|
||||
// Compile pixel shader
|
||||
hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"PShader", "ps_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_pixelShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreatePixelShader(_pixelShaderByteCode->GetBufferPointer(), _pixelShaderByteCode->GetBufferSize(), NULL, _pixelShader.GetAddressOf()));
|
||||
}
|
||||
|
||||
|
||||
void MeshRenderer::BuildVertexLayout()
|
||||
{
|
||||
// Create the vertex input layout. This tells DirectX the format
|
||||
// of each of the vertices we are sending to it.
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
ThrowIfFailed(_device->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc), _vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), _layout.GetAddressOf()));
|
||||
}
|
||||
|
||||
void MeshRenderer::BuildConstantBuffer()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = sizeof(CBUFFER);
|
||||
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void MeshRenderer::BuildBlendState()
|
||||
{
|
||||
D3D11_BLEND_DESC transparentDesc = { 0 };
|
||||
transparentDesc.AlphaToCoverageEnable = false;
|
||||
transparentDesc.IndependentBlendEnable = false;
|
||||
transparentDesc.RenderTarget[0].BlendEnable = true;
|
||||
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
ThrowIfFailed(_device->CreateBlendState(&transparentDesc, _transparentBlendState.GetAddressOf()));
|
||||
}
|
||||
|
||||
void MeshRenderer::BuildRendererState()
|
||||
{
|
||||
// Set default and no cull rasteriser states
|
||||
D3D11_RASTERIZER_DESC rasteriserDesc;
|
||||
rasteriserDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasteriserDesc.CullMode = D3D11_CULL_BACK;
|
||||
rasteriserDesc.FrontCounterClockwise = false;
|
||||
rasteriserDesc.DepthBias = 0;
|
||||
rasteriserDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasteriserDesc.DepthBiasClamp = 0.0f;
|
||||
rasteriserDesc.DepthClipEnable = true;
|
||||
rasteriserDesc.ScissorEnable = false;
|
||||
rasteriserDesc.MultisampleEnable = false;
|
||||
rasteriserDesc.AntialiasedLineEnable = false;
|
||||
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _defaultRasteriserState.GetAddressOf()));
|
||||
rasteriserDesc.CullMode = D3D11_CULL_NONE;
|
||||
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _noCullRasteriserState.GetAddressOf()));
|
||||
}
|
||||
|
58
Graphics2/MeshRenderer.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include "SharedMethods.h"
|
||||
#include "Renderer.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
class MeshRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
|
||||
void SetMesh(shared_ptr<Mesh> mesh);
|
||||
void SetWorldTransformation(FXMMATRIX worldTransformation);
|
||||
void SetAmbientLight(XMFLOAT4 ambientLight);
|
||||
void SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour);
|
||||
void SetCameraPosition(XMFLOAT4 cameraPosition);
|
||||
bool Initialise();
|
||||
void Render();
|
||||
void Shutdown(void);
|
||||
|
||||
private:
|
||||
shared_ptr<Mesh> _mesh;
|
||||
XMFLOAT4X4 _worldTransformation;
|
||||
XMFLOAT4 _ambientLight;
|
||||
XMFLOAT4 _directionalLightVector;
|
||||
XMFLOAT4 _directionalLightColour;
|
||||
XMFLOAT4 _cameraPosition;
|
||||
|
||||
ComPtr<ID3D11Device> _device;
|
||||
ComPtr<ID3D11DeviceContext> _deviceContext;
|
||||
|
||||
ComPtr<ID3D11Buffer> _vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> _indexBuffer;
|
||||
|
||||
ComPtr<ID3DBlob> _vertexShaderByteCode = nullptr;
|
||||
ComPtr<ID3DBlob> _pixelShaderByteCode = nullptr;
|
||||
ComPtr<ID3D11VertexShader> _vertexShader;
|
||||
ComPtr<ID3D11PixelShader> _pixelShader;
|
||||
ComPtr<ID3D11InputLayout> _layout;
|
||||
ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _texture;;
|
||||
|
||||
ComPtr<ID3D11BlendState> _transparentBlendState;
|
||||
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _noCullRasteriserState;
|
||||
|
||||
CBUFFER _cBuffer;
|
||||
|
||||
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildBlendState();
|
||||
void BuildRendererState();
|
||||
|
||||
void RenderNode(shared_ptr<Node> node, bool renderTransparent);
|
||||
};
|
||||
|
BIN
Graphics2/Models/Plane/Bonanza.3ds
Normal file
BIN
Graphics2/Models/Plane/Defaul.jpg
Normal file
After Width: | Height: | Size: 631 B |
BIN
Graphics2/Models/Plane/anthra.jpg
Normal file
After Width: | Height: | Size: 631 B |
BIN
Graphics2/Models/Plane/fin.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
Graphics2/Models/Plane/fin1.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
Graphics2/Models/Plane/fus.jpg
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
Graphics2/Models/Plane/fus1.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
Graphics2/Models/Plane/lwin.jpg
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
Graphics2/Models/Plane/lwin1.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
Graphics2/Models/Plane/nose.jpg
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
Graphics2/Models/Plane/panel.jpg
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
Graphics2/Models/Plane/red.jpg
Normal file
After Width: | Height: | Size: 633 B |
BIN
Graphics2/Models/Plane/rwin.jpg
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
Graphics2/Models/Plane/rwin1.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
Graphics2/Models/Plane/tail.jpg
Normal file
After Width: | Height: | Size: 631 B |
BIN
Graphics2/Models/Plane/tail1.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
13
Graphics2/Renderer.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
Renderer() {}
|
||||
virtual ~Renderer() {}
|
||||
|
||||
virtual bool Initialise() = 0;
|
||||
virtual void Render() = 0;
|
||||
virtual void Shutdown() {};
|
||||
};
|
||||
|
479
Graphics2/ResourceManager.cpp
Normal file
@ -0,0 +1,479 @@
|
||||
#include "ResourceManager.h"
|
||||
#include "DirectXFramework.h"
|
||||
#include <sstream>
|
||||
#include "WICTextureLoader.h"
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include "MeshRenderer.h"
|
||||
#include "SubMeshRenderer.h"
|
||||
|
||||
#pragma comment(lib, "../Assimp/lib/release/assimp-vc140-mt.lib")
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
// Utility functions to convert from wstring to string and back
|
||||
// Copied from https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string
|
||||
|
||||
wstring s2ws(const std::string& str)
|
||||
{
|
||||
using convert_typeX = std::codecvt_utf8<wchar_t>;
|
||||
std::wstring_convert<convert_typeX, wchar_t> converterX;
|
||||
|
||||
return converterX.from_bytes(str);
|
||||
}
|
||||
|
||||
string ws2s(const std::wstring& wstr)
|
||||
{
|
||||
using convert_typeX = std::codecvt_utf8<wchar_t>;
|
||||
std::wstring_convert<convert_typeX, wchar_t> converterX;
|
||||
|
||||
return converterX.to_bytes(wstr);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
ResourceManager::ResourceManager()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
|
||||
// Create a default texture for use where none is specified. If white.png is not available, then
|
||||
// the default texture will be null, i.e. black. This causes problems for materials that do not
|
||||
// provide a texture, unless we provide a totally different shader just for those cases. That
|
||||
// might be more efficient, but is a lot of work at this stage for little gain.
|
||||
if (FAILED(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
L"white.png",
|
||||
nullptr,
|
||||
_defaultTexture.GetAddressOf()
|
||||
)))
|
||||
{
|
||||
_defaultTexture = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager(void)
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr<Renderer> ResourceManager::GetRenderer(wstring rendererName)
|
||||
{
|
||||
// Return different renderers based on the name requested
|
||||
// At the moment, only one renderer is handled, but more would
|
||||
// be added as different shaders are required, etc
|
||||
//
|
||||
// Look to see if an instance of the renderer has already been created
|
||||
RendererResourceMap::iterator it = _rendererResources.find(rendererName);
|
||||
if (it != _rendererResources.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rendererName == L"PNT")
|
||||
{
|
||||
shared_ptr<Renderer> renderer = make_shared<MeshRenderer>();
|
||||
_rendererResources[rendererName] = renderer;
|
||||
return renderer;
|
||||
}
|
||||
else if (rendererName == L"SMR")
|
||||
{
|
||||
shared_ptr<Renderer> renderer = make_shared<SubMeshRenderer>();
|
||||
_rendererResources[rendererName] = renderer;
|
||||
return renderer;
|
||||
}
|
||||
// If we wanted additional renderers, we could test for them here
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<Mesh> ResourceManager::GetMesh(wstring modelName)
|
||||
{
|
||||
// CHeck to see if the mesh has already been loaded
|
||||
MeshResourceMap::iterator it = _meshResources.find(modelName);
|
||||
if (it != _meshResources.end())
|
||||
{
|
||||
// Update reference count and return pointer to existing mesh
|
||||
it->second.ReferenceCount++;
|
||||
return it->second.MeshPointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the first request for this model. Load the mesh and
|
||||
// save a reference to it.
|
||||
shared_ptr<Mesh> mesh = LoadModelFromFile(modelName);
|
||||
if (mesh != nullptr)
|
||||
{
|
||||
MeshResourceStruct resourceStruct;
|
||||
resourceStruct.ReferenceCount = 1;
|
||||
resourceStruct.MeshPointer = mesh;
|
||||
_meshResources[modelName] = resourceStruct;
|
||||
return mesh;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::ReleaseMesh(wstring modelName)
|
||||
{
|
||||
MeshResourceMap::iterator it = _meshResources.find(modelName);
|
||||
if (it != _meshResources.end())
|
||||
{
|
||||
it->second.ReferenceCount--;
|
||||
if (it->second.ReferenceCount == 0)
|
||||
{
|
||||
// Release any materials used by this mesh
|
||||
shared_ptr<Mesh> mesh = it->second.MeshPointer;
|
||||
unsigned int subMeshCount = static_cast<unsigned int>(mesh->GetSubMeshCount());
|
||||
// Loop through all submeshes in the mesh
|
||||
for (unsigned int i = 0; i < subMeshCount; i++)
|
||||
{
|
||||
shared_ptr<SubMesh> subMesh = mesh->GetSubMesh(i);
|
||||
wstring materialName = subMesh->GetMaterial()->GetMaterialName();
|
||||
ReleaseMaterial(materialName);
|
||||
}
|
||||
// If no other nodes are using this mesh, remove it frmo the map
|
||||
// (which will also release the resources).
|
||||
it->second.MeshPointer = nullptr;
|
||||
_meshResources.erase(modelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::CreateMaterialFromTexture(wstring textureName)
|
||||
{
|
||||
// We have no diffuse or specular colours here since we are just building a default material structure
|
||||
// based on a provided texture. Just use the texture name as the material name in this case
|
||||
return InitialiseMaterial(textureName,
|
||||
XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
0,
|
||||
1.0f,
|
||||
textureName);
|
||||
}
|
||||
|
||||
void ResourceManager::CreateMaterialWithNoTexture(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity)
|
||||
{
|
||||
return InitialiseMaterial(materialName, diffuseColour, specularColour, shininess, opacity, L"");
|
||||
}
|
||||
|
||||
void ResourceManager::CreateMaterial(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, wstring textureName)
|
||||
{
|
||||
return InitialiseMaterial(materialName, diffuseColour, specularColour, shininess, opacity, textureName);
|
||||
}
|
||||
|
||||
shared_ptr<Material> ResourceManager::GetMaterial(wstring materialName)
|
||||
{
|
||||
// This works a bit different to the GetMesh method. We can only find
|
||||
// materials we have previously created (usually when the mesh was loaded
|
||||
// from the file).
|
||||
MaterialResourceMap::iterator it = _materialResources.find(materialName);
|
||||
if (it != _materialResources.end())
|
||||
{
|
||||
it->second.ReferenceCount++;
|
||||
return it->second.MaterialPointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Material not previously created.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::ReleaseMaterial(wstring materialName)
|
||||
{
|
||||
MaterialResourceMap::iterator it = _materialResources.find(materialName);
|
||||
if (it != _materialResources.end())
|
||||
{
|
||||
it->second.ReferenceCount--;
|
||||
if (it->second.ReferenceCount == 0)
|
||||
{
|
||||
it->second.MaterialPointer = nullptr;
|
||||
_meshResources.erase(materialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::InitialiseMaterial(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, wstring textureName)
|
||||
{
|
||||
MaterialResourceMap::iterator it = _materialResources.find(materialName);
|
||||
if (it == _materialResources.end())
|
||||
{
|
||||
// We are creating the material for the first time
|
||||
ComPtr<ID3D11ShaderResourceView> texture;
|
||||
if (textureName.size() > 0)
|
||||
{
|
||||
// A texture was specified. Try to load it.
|
||||
if (FAILED(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
textureName.c_str(),
|
||||
nullptr,
|
||||
texture.GetAddressOf()
|
||||
)))
|
||||
{
|
||||
// If we cannot load the texture, then just use the default.
|
||||
texture = _defaultTexture;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = _defaultTexture;
|
||||
}
|
||||
shared_ptr<Material> material = make_shared<Material>(materialName, diffuseColour, specularColour, shininess, opacity, texture);
|
||||
MaterialResourceStruct resourceStruct;
|
||||
resourceStruct.ReferenceCount = 0;
|
||||
resourceStruct.MaterialPointer = material;
|
||||
_materialResources[materialName] = resourceStruct;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Node> ResourceManager::CreateNodes(aiNode * sceneNode)
|
||||
{
|
||||
shared_ptr<Node> node = make_shared<Node>();
|
||||
node->SetName(s2ws(string(sceneNode->mName.C_Str())));
|
||||
// Get the meshes associated with this node
|
||||
unsigned int meshCount = sceneNode->mNumMeshes;
|
||||
for (unsigned int i = 0; i < meshCount; i++)
|
||||
{
|
||||
node->AddMesh(sceneNode->mMeshes[i]);
|
||||
}
|
||||
// Now process the children of this node
|
||||
unsigned int childrenCount = sceneNode->mNumChildren;
|
||||
for (unsigned int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
node->AddChild(CreateNodes(sceneNode->mChildren[i]));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
shared_ptr<Mesh> ResourceManager::LoadModelFromFile(wstring modelName)
|
||||
{
|
||||
ComPtr<ID3D11Buffer> vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> indexBuffer;
|
||||
wstring * materials = nullptr;
|
||||
|
||||
Importer importer;
|
||||
|
||||
unsigned int postProcessSteps = aiProcess_Triangulate |
|
||||
aiProcess_ConvertToLeftHanded;
|
||||
string modelNameUTF8 = ws2s(modelName);
|
||||
const aiScene * scene = importer.ReadFile(modelNameUTF8.c_str(), postProcessSteps);
|
||||
if (!scene)
|
||||
{
|
||||
// If failed to load, there is nothing to do
|
||||
return nullptr;
|
||||
}
|
||||
if (!scene->HasMeshes())
|
||||
{
|
||||
//If there are no meshes, then there is nothing to do.
|
||||
return nullptr;
|
||||
}
|
||||
if (scene->HasMaterials())
|
||||
{
|
||||
// We need to find the directory part of the model name since we will need to add it to any texture names.
|
||||
// There is definately a more elegant and accurate way to do this using Windows API calls, but this is a quick
|
||||
// and dirty approach
|
||||
string::size_type slashIndex = modelNameUTF8.find_last_of("\\");
|
||||
string directory;
|
||||
if (slashIndex == string::npos)
|
||||
{
|
||||
directory = ".";
|
||||
}
|
||||
else if (slashIndex == 0)
|
||||
{
|
||||
directory = "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = modelNameUTF8.substr(0, slashIndex);
|
||||
}
|
||||
// Let's deal with the materials/textures first
|
||||
materials = new wstring[scene->mNumMaterials];
|
||||
for (unsigned int i = 0; i < scene->mNumMaterials; i++)
|
||||
{
|
||||
// Get the core material properties. Ideally, we would be looking for more information
|
||||
// e.g. emissive colour, etc. This is a task for later.
|
||||
aiMaterial * material = scene->mMaterials[i];
|
||||
|
||||
aiColor3D &defaultColour = aiColor3D(0.0f, 0.0f, 0.0f);
|
||||
aiColor3D& diffuseColour = aiColor3D(0.0f, 0.0f, 0.0f);
|
||||
if (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColour) != aiReturn_SUCCESS)
|
||||
{
|
||||
diffuseColour = defaultColour;
|
||||
}
|
||||
aiColor3D& specularColour = aiColor3D(0.0f, 0.0f, 0.0f);
|
||||
if (material->Get(AI_MATKEY_COLOR_SPECULAR, specularColour) != aiReturn_SUCCESS)
|
||||
{
|
||||
specularColour = defaultColour;
|
||||
}
|
||||
float defaultShininess = 0.0f;
|
||||
float& shininess = defaultShininess;
|
||||
material->Get(AI_MATKEY_SHININESS, shininess);
|
||||
float defaultOpacity = 1.0f;
|
||||
float& opacity = defaultOpacity;
|
||||
material->Get(AI_MATKEY_OPACITY, opacity);
|
||||
bool defaultTwoSided = false;
|
||||
bool& twoSided = defaultTwoSided;
|
||||
material->Get(AI_MATKEY_TWOSIDED, twoSided);
|
||||
string fullTextureNamePath = "";
|
||||
if (material->GetTextureCount(aiTextureType_DIFFUSE) > 0)
|
||||
{
|
||||
aiString textureName;
|
||||
float blendFactor;
|
||||
aiTextureOp blendOp;
|
||||
if (material->GetTexture(aiTextureType_DIFFUSE, 0, &textureName, NULL, NULL, &blendFactor, &blendOp, NULL) == AI_SUCCESS)
|
||||
{
|
||||
// Get full path to texture by prepending the same folder as included in the model name. This
|
||||
// does assume that textures are in the same folder as the model files
|
||||
fullTextureNamePath = directory + "\\" + textureName.data;
|
||||
}
|
||||
}
|
||||
// Now create a unique name for the material based on the model name and loop count
|
||||
stringstream materialNameStream;
|
||||
materialNameStream << modelNameUTF8 << i;
|
||||
string materialName = materialNameStream.str();
|
||||
wstring materialNameWS = s2ws(materialName);
|
||||
CreateMaterial(materialNameWS,
|
||||
XMFLOAT4(diffuseColour.r, diffuseColour.g, diffuseColour.b, 1.0f),
|
||||
XMFLOAT4(specularColour.r, specularColour.g, specularColour.b, 1.0f),
|
||||
shininess,
|
||||
opacity,
|
||||
s2ws(fullTextureNamePath));
|
||||
materials[i] = materialNameWS;
|
||||
}
|
||||
}
|
||||
// Now we have created all of the materials, build up the mesh
|
||||
shared_ptr<Mesh> resourceMesh = make_shared<Mesh>();
|
||||
for (unsigned int sm = 0; sm < scene->mNumMeshes; sm++)
|
||||
{
|
||||
aiMesh * subMesh = scene->mMeshes[sm];
|
||||
unsigned int numVertices = subMesh->mNumVertices;
|
||||
bool hasNormals = subMesh->HasNormals();
|
||||
bool hasTexCoords = subMesh->HasTextureCoords(0);
|
||||
if (numVertices == 0 || !hasNormals)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// Build up our vertex structure
|
||||
aiVector3D * subMeshVertices = subMesh->mVertices;
|
||||
aiVector3D * subMeshNormals = subMesh->mNormals;
|
||||
// We only handle one set of UV coordinates at the moment. Again, handling multiple sets of UV
|
||||
// coordinates is a future enhancement.
|
||||
aiVector3D * subMeshTexCoords = subMesh->mTextureCoords[0];
|
||||
VERTEX * modelVertices = new VERTEX[numVertices];
|
||||
VERTEX * currentVertex = modelVertices;
|
||||
for (unsigned int i = 0; i < numVertices; i++)
|
||||
{
|
||||
currentVertex->Position = XMFLOAT3(subMeshVertices->x, subMeshVertices->y, subMeshVertices->z);
|
||||
currentVertex->Normal = XMFLOAT3(subMeshNormals->x, subMeshNormals->y, subMeshNormals->z);
|
||||
subMeshVertices++;
|
||||
subMeshNormals++;
|
||||
if (!hasTexCoords)
|
||||
{
|
||||
// If the model does not have texture coordinates, set them to 0
|
||||
currentVertex->TexCoord = XMFLOAT2(0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle negative texture coordinates by wrapping them to positive. This should
|
||||
// ideally be handled in the shader. Note we are assuming that negative coordinates
|
||||
// here are no smaller than -1.0 - this may not be a valid assumption.
|
||||
if (subMeshTexCoords->x < 0)
|
||||
{
|
||||
currentVertex->TexCoord.x = subMeshTexCoords->x + 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentVertex->TexCoord.x = subMeshTexCoords->x;
|
||||
}
|
||||
if (subMeshTexCoords->y < 0)
|
||||
{
|
||||
currentVertex->TexCoord.y = subMeshTexCoords->y + 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentVertex->TexCoord.y = subMeshTexCoords->y;
|
||||
}
|
||||
subMeshTexCoords++;
|
||||
}
|
||||
currentVertex++;
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC vertexBufferDescriptor;
|
||||
vertexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
vertexBufferDescriptor.ByteWidth = sizeof(VERTEX) * numVertices;
|
||||
vertexBufferDescriptor.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexBufferDescriptor.CPUAccessFlags = 0;
|
||||
vertexBufferDescriptor.MiscFlags = 0;
|
||||
vertexBufferDescriptor.StructureByteStride = 0;
|
||||
|
||||
// Now set up a structure that tells DirectX where to get the
|
||||
// data for the vertices from
|
||||
D3D11_SUBRESOURCE_DATA vertexInitialisationData;
|
||||
vertexInitialisationData.pSysMem = modelVertices;
|
||||
|
||||
// and create the vertex buffer
|
||||
if (FAILED(_device->CreateBuffer(&vertexBufferDescriptor, &vertexInitialisationData, vertexBuffer.GetAddressOf())))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Now extract the indices from the file
|
||||
unsigned int numberOfFaces = subMesh->mNumFaces;
|
||||
unsigned int numberOfIndices = numberOfFaces * 3;
|
||||
aiFace * subMeshFaces = subMesh->mFaces;
|
||||
if (subMeshFaces->mNumIndices != 3)
|
||||
{
|
||||
// We are not dealing with triangles, so we cannot handle it
|
||||
return nullptr;
|
||||
}
|
||||
unsigned int * modelIndices = new unsigned int[numberOfIndices * 3];
|
||||
unsigned int * currentIndex = modelIndices;
|
||||
for (unsigned int i = 0; i < numberOfFaces; i++)
|
||||
{
|
||||
*currentIndex++ = subMeshFaces->mIndices[0];
|
||||
*currentIndex++ = subMeshFaces->mIndices[1];
|
||||
*currentIndex++ = subMeshFaces->mIndices[2];
|
||||
subMeshFaces++;
|
||||
}
|
||||
// Setup the structure that specifies how big the index
|
||||
// buffer should be
|
||||
D3D11_BUFFER_DESC indexBufferDescriptor;
|
||||
indexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
indexBufferDescriptor.ByteWidth = sizeof(UINT) * numberOfIndices * 3;
|
||||
indexBufferDescriptor.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexBufferDescriptor.CPUAccessFlags = 0;
|
||||
indexBufferDescriptor.MiscFlags = 0;
|
||||
indexBufferDescriptor.StructureByteStride = 0;
|
||||
|
||||
// Now set up a structure that tells DirectX where to get the
|
||||
// data for the indices from
|
||||
D3D11_SUBRESOURCE_DATA indexInitialisationData;
|
||||
indexInitialisationData.pSysMem = modelIndices;
|
||||
|
||||
// and create the index buffer
|
||||
if (FAILED(_device->CreateBuffer(&indexBufferDescriptor, &indexInitialisationData, indexBuffer.GetAddressOf())))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Do we have a material associated with this mesh?
|
||||
shared_ptr<Material> material = nullptr;
|
||||
if (scene->HasMaterials())
|
||||
{
|
||||
material = GetMaterial(materials[subMesh->mMaterialIndex]);
|
||||
}
|
||||
shared_ptr<SubMesh> resourceSubMesh = make_shared<SubMesh>(vertexBuffer, indexBuffer, numVertices, numberOfIndices, material);
|
||||
resourceMesh->AddSubMesh(resourceSubMesh);
|
||||
delete[] modelVertices;
|
||||
delete[] modelIndices;
|
||||
}
|
||||
// Now build the hierarchy of nodes
|
||||
resourceMesh->SetRootNode(CreateNodes(scene->mRootNode));
|
||||
return resourceMesh;
|
||||
}
|
65
Graphics2/ResourceManager.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include "Mesh.h"
|
||||
#include "Renderer.h"
|
||||
#include <map>
|
||||
#include <assimp\importer.hpp>
|
||||
#include <assimp\scene.h>
|
||||
#include <assimp\postprocess.h>
|
||||
|
||||
struct VERTEX
|
||||
{
|
||||
XMFLOAT3 Position;
|
||||
XMFLOAT3 Normal;
|
||||
XMFLOAT2 TexCoord;
|
||||
};
|
||||
|
||||
struct MeshResourceStruct
|
||||
{
|
||||
unsigned int ReferenceCount;
|
||||
shared_ptr<Mesh> MeshPointer;
|
||||
};
|
||||
|
||||
typedef map<wstring, MeshResourceStruct> MeshResourceMap;
|
||||
|
||||
struct MaterialResourceStruct
|
||||
{
|
||||
unsigned int ReferenceCount;
|
||||
shared_ptr<Material> MaterialPointer;
|
||||
};
|
||||
|
||||
typedef map<wstring, MaterialResourceStruct> MaterialResourceMap;
|
||||
|
||||
typedef map<wstring, shared_ptr<Renderer>> RendererResourceMap;
|
||||
|
||||
class ResourceManager
|
||||
{
|
||||
public:
|
||||
ResourceManager();
|
||||
~ResourceManager();
|
||||
|
||||
shared_ptr<Renderer> GetRenderer(wstring rendererName);
|
||||
|
||||
shared_ptr<Mesh> GetMesh(wstring modelName);
|
||||
void ReleaseMesh(wstring modelName);
|
||||
|
||||
void CreateMaterialFromTexture(wstring textureName);
|
||||
void CreateMaterialWithNoTexture(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity);
|
||||
void CreateMaterial(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, wstring textureName);
|
||||
shared_ptr<Material> GetMaterial(wstring materialName);
|
||||
void ReleaseMaterial(wstring materialName);
|
||||
|
||||
private:
|
||||
MeshResourceMap _meshResources;
|
||||
MaterialResourceMap _materialResources;
|
||||
RendererResourceMap _rendererResources;
|
||||
|
||||
ComPtr<ID3D11Device> _device;
|
||||
ComPtr<ID3D11DeviceContext> _deviceContext;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _defaultTexture;
|
||||
|
||||
shared_ptr<Node> CreateNodes(aiNode * sceneNode);
|
||||
shared_ptr<Mesh> LoadModelFromFile(wstring modelName);
|
||||
void InitialiseMaterial(wstring materialName, XMFLOAT4 diffuseColour, XMFLOAT4 specularColour, float shininess, float opacity, wstring textureName);
|
||||
};
|
||||
|
80
Graphics2/SceneGraph.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "SceneGraph.h"
|
||||
|
||||
bool SceneGraph::Initialise()
|
||||
{
|
||||
bool currentStatus = true;
|
||||
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
currentStatus = currentSceneGraphPtr->Initialise();
|
||||
if (!currentStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return currentStatus;
|
||||
}
|
||||
|
||||
void SceneGraph::Update(FXMMATRIX& currentWorldTransformation)
|
||||
{
|
||||
SceneNode::Update(currentWorldTransformation);
|
||||
|
||||
XMMATRIX combinedWorldTransform = XMLoadFloat4x4(&_combinedWorldTransformation);
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
currentSceneGraphPtr->Update(combinedWorldTransform);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraph::Render()
|
||||
{
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
currentSceneGraphPtr->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraph::Shutdown()
|
||||
{
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
currentSceneGraphPtr->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraph::Add(SceneNodePointer node)
|
||||
{
|
||||
_children.push_back(node);
|
||||
}
|
||||
|
||||
void SceneGraph::Remove(SceneNodePointer node)
|
||||
{
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
if (currentSceneGraphPtr == node)
|
||||
{
|
||||
_children.remove(currentSceneGraphPtr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SceneNodePointer SceneGraph::Find(wstring name)
|
||||
{
|
||||
if (_name == name)
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
SceneNodePointer foundValue = nullptr;
|
||||
for (SceneNodePointer& currentSceneGraphPtr : _children)
|
||||
{
|
||||
foundValue = currentSceneGraphPtr->Find(name);
|
||||
if (foundValue != nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return foundValue;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include "SceneNode.h"
|
||||
|
||||
class SceneGraph : public SceneNode
|
||||
@ -8,19 +9,19 @@ public:
|
||||
SceneGraph(wstring name) : SceneNode(name) {};
|
||||
~SceneGraph(void) {};
|
||||
|
||||
virtual bool Initialise(void);
|
||||
virtual void Update(FXMMATRIX& currentWorldTransformation);
|
||||
virtual void Render(void);
|
||||
virtual void Shutdown(void);
|
||||
bool Initialise(void);
|
||||
void Update(FXMMATRIX& currentWorldTransformation);
|
||||
void Render(void);
|
||||
void Shutdown(void);
|
||||
|
||||
void Add(SceneNodePointer node);
|
||||
void Remove(SceneNodePointer node);
|
||||
SceneNodePointer Find(wstring name);
|
||||
|
||||
//private:
|
||||
|
||||
private:
|
||||
// Here you need to add whatever collection you are going to
|
||||
// use to store the children of this scene graph
|
||||
list<SceneNodePointer> _children;
|
||||
};
|
||||
|
||||
typedef shared_ptr<SceneGraph> SceneGraphPointer;
|
||||
typedef shared_ptr<SceneGraph> SceneGraphPointer;
|
||||
|
0
Graphics2/SceneNode.cpp
Normal file
@ -23,6 +23,8 @@ public:
|
||||
virtual void Render() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual void DoTestUpdate(float inputTest) { _testInt = inputTest; }
|
||||
|
||||
void SetWorldTransform(FXMMATRIX& worldTransformation) { XMStoreFloat4x4(&_worldTransformation, worldTransformation); }
|
||||
|
||||
// Although only required in the composite class, these are provided
|
||||
@ -35,5 +37,6 @@ protected:
|
||||
XMFLOAT4X4 _worldTransformation;
|
||||
XMFLOAT4X4 _combinedWorldTransformation;
|
||||
wstring _name;
|
||||
float _testInt = 0.0f;
|
||||
};
|
||||
|
||||
|
7
Graphics2/SharedMethods.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "SharedMethods.h"
|
||||
|
||||
XMMATRIX SharedMethods::RotateFromPoint(float x, float y, float z, XMMATRIX rotationMatrix)
|
||||
{
|
||||
// Translates a matrix to a point, rotates and then returns back to where it was
|
||||
return XMMatrixTranslation(x, y, z) * rotationMatrix * XMMatrixTranslation(-x, -y, -z);
|
||||
}
|
23
Graphics2/SharedMethods.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
|
||||
struct CBUFFER
|
||||
{
|
||||
XMMATRIX CompleteTransformation;
|
||||
XMMATRIX WorldTransformation;
|
||||
XMFLOAT4 CameraPosition;
|
||||
XMVECTOR LightVector;
|
||||
XMFLOAT4 LightColor;
|
||||
XMFLOAT4 AmbientColor;
|
||||
XMFLOAT4 DiffuseCoefficient;
|
||||
XMFLOAT4 SpecularCoefficient;
|
||||
float Shininess;
|
||||
float Opacity;
|
||||
float Padding[2];
|
||||
};
|
||||
|
||||
namespace SharedMethods
|
||||
{
|
||||
XMMATRIX RotateFromPoint(float x, float y, float z, XMMATRIX rotationMatrix);
|
||||
};
|
||||
|
63
Graphics2/SplitMeshNode.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "SplitMeshNode.h"
|
||||
|
||||
SplitMeshNode::SplitMeshNode(wstring name, wstring modelName)
|
||||
{
|
||||
_modelName = modelName;
|
||||
}
|
||||
|
||||
bool SplitMeshNode::Initialise()
|
||||
{
|
||||
bool currentStatus = true;
|
||||
|
||||
_resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager();
|
||||
_mesh = _resourceManager->GetMesh(_modelName);
|
||||
if (_mesh == nullptr)
|
||||
{
|
||||
currentStatus = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Add(AddMeshNode(_mesh->GetRootNode()));
|
||||
}
|
||||
|
||||
if (currentStatus)
|
||||
{
|
||||
currentStatus = SceneGraph::Initialise();
|
||||
}
|
||||
|
||||
return currentStatus;
|
||||
}
|
||||
|
||||
SceneGraphPointer SplitMeshNode::AddMeshNode(shared_ptr<Node> node)
|
||||
{
|
||||
unsigned int subMeshCount = (unsigned int)node->GetMeshCount();
|
||||
SceneGraphPointer currentNodeGraph = make_shared<SceneGraph>(node->GetName());
|
||||
|
||||
/*string nameString;
|
||||
for (char x : node->GetName())
|
||||
{
|
||||
nameString += x;
|
||||
}
|
||||
|
||||
fileOut << string(depth, '-') + " " + nameString << endl;*/
|
||||
|
||||
// Loop through all submeshes in the mesh
|
||||
for (unsigned int i = 0; i < subMeshCount; i++)
|
||||
{
|
||||
unsigned int meshIndex = node->GetMesh(i);
|
||||
shared_ptr<SubMesh> subMesh = _mesh->GetSubMesh(meshIndex);
|
||||
shared_ptr<SubMeshNode> subNode = make_shared<SubMeshNode>(node->GetName() + L"_" + to_wstring(i), subMesh);
|
||||
subNode->SetWorldTransform(XMMatrixIdentity());
|
||||
currentNodeGraph->Add(subNode);
|
||||
}
|
||||
|
||||
// Render the children
|
||||
unsigned int childrenCount = (unsigned int)node->GetChildrenCount();
|
||||
// Loop through all submeshes in the mesh, rendering them
|
||||
for (unsigned int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
currentNodeGraph->Add(AddMeshNode(node->GetChild(i)));
|
||||
}
|
||||
|
||||
return currentNodeGraph;
|
||||
}
|
22
Graphics2/SplitMeshNode.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include "SceneGraph.h"
|
||||
#include "SubMeshNode.h"
|
||||
|
||||
class SplitMeshNode : public SceneGraph
|
||||
{
|
||||
public:
|
||||
SplitMeshNode(wstring name, wstring modelName);
|
||||
bool Initialise(void);
|
||||
SceneGraphPointer AddMeshNode(shared_ptr<Node> node);
|
||||
|
||||
private:
|
||||
shared_ptr<SubMeshRenderer> _renderer;
|
||||
|
||||
wstring _modelName;
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
shared_ptr<Mesh> _mesh;
|
||||
|
||||
bool _isInit = false;
|
||||
};
|
||||
|
26
Graphics2/SubMeshNode.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "SubMeshNode.h"
|
||||
|
||||
bool SubMeshNode::Initialise()
|
||||
{
|
||||
_resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager();
|
||||
_renderer = dynamic_pointer_cast<SubMeshRenderer>(_resourceManager->GetRenderer(L"SMR"));
|
||||
if (_subMesh == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _renderer->Initialise();
|
||||
}
|
||||
|
||||
void SubMeshNode::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void SubMeshNode::Render()
|
||||
{
|
||||
_renderer->SetSubMesh(_subMesh);
|
||||
_renderer->SetWorldTransformation(XMLoadFloat4x4(&_combinedWorldTransformation));
|
||||
_renderer->SetCameraPosition(XMFLOAT4(0.0f, 0.0f, -100.0f, 1.0f));
|
||||
_renderer->SetAmbientLight(XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
_renderer->SetDirectionalLight(XMVectorSet(0.0f, -1.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
_renderer->Render();
|
||||
}
|
21
Graphics2/SubMeshNode.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include "SceneNode.h"
|
||||
#include "SubMeshRenderer.h"
|
||||
|
||||
class SubMeshNode : public SceneNode
|
||||
{
|
||||
public:
|
||||
SubMeshNode(wstring name, shared_ptr<SubMesh> subMesh) : SceneNode(name) { _subMesh = subMesh; }
|
||||
|
||||
bool Initialise();
|
||||
void Render();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
shared_ptr<SubMeshRenderer> _renderer;
|
||||
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
shared_ptr<SubMesh> _subMesh;
|
||||
};
|
||||
|
203
Graphics2/SubMeshRenderer.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
#include "SubMeshRenderer.h"
|
||||
|
||||
void SubMeshRenderer::SetSubMesh(shared_ptr<SubMesh> subMesh)
|
||||
{
|
||||
_subMesh = subMesh;
|
||||
}
|
||||
|
||||
void SubMeshRenderer::SetWorldTransformation(FXMMATRIX worldTransformation)
|
||||
{
|
||||
XMStoreFloat4x4(&_worldTransformation, worldTransformation);
|
||||
}
|
||||
|
||||
void SubMeshRenderer::SetAmbientLight(XMFLOAT4 ambientLight)
|
||||
{
|
||||
_ambientLight = ambientLight;
|
||||
}
|
||||
|
||||
void SubMeshRenderer::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour)
|
||||
{
|
||||
_directionalLightColour = lightColour;
|
||||
XMStoreFloat4(&_directionalLightVector, lightVector);
|
||||
}
|
||||
|
||||
void SubMeshRenderer::SetCameraPosition(XMFLOAT4 cameraPosition)
|
||||
{
|
||||
_cameraPosition = cameraPosition;
|
||||
}
|
||||
|
||||
bool SubMeshRenderer::Initialise()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
BuildShaders();
|
||||
BuildVertexLayout();
|
||||
BuildConstantBuffer();
|
||||
BuildBlendState();
|
||||
BuildRendererState();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SubMeshRenderer::Render()
|
||||
{
|
||||
// Turn off back face culling while we render a mesh.
|
||||
// We do this since ASSIMP does not appear to be setting the
|
||||
// TWOSIDED property on materials correctly. Without turning off
|
||||
// back face culling, some materials do not render correctly.
|
||||
_deviceContext->RSSetState(_noCullRasteriserState.Get());
|
||||
|
||||
XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation();
|
||||
XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetViewTransformation();
|
||||
|
||||
XMMATRIX completeTransformation = XMLoadFloat4x4(&_worldTransformation) * viewTransformation * projectionTransformation;
|
||||
|
||||
// Draw the first cube
|
||||
|
||||
_cBuffer.CompleteTransformation = completeTransformation;
|
||||
_cBuffer.WorldTransformation = XMLoadFloat4x4(&_worldTransformation);
|
||||
_cBuffer.AmbientColor = _ambientLight;
|
||||
_cBuffer.LightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector));
|
||||
_cBuffer.LightColor = _directionalLightColour;
|
||||
_cBuffer.CameraPosition = _cameraPosition;
|
||||
|
||||
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
|
||||
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
|
||||
_deviceContext->IASetInputLayout(_layout.Get());
|
||||
|
||||
// Set the blend state correctly to handle opacity
|
||||
float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
_deviceContext->OMSetBlendState(_transparentBlendState.Get(), blendFactors, 0xffffffff);
|
||||
|
||||
shared_ptr<Material> material = _subMesh->GetMaterial();
|
||||
float opacity = material->GetOpacity();
|
||||
|
||||
UINT stride = sizeof(VERTEX);
|
||||
UINT offset = 0;
|
||||
_vertexBuffer = _subMesh->GetVertexBuffer();
|
||||
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
|
||||
_indexBuffer = _subMesh->GetIndexBuffer();
|
||||
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
|
||||
_cBuffer.DiffuseCoefficient = material->GetDiffuseColour();
|
||||
_cBuffer.SpecularCoefficient = material->GetSpecularColour();
|
||||
_cBuffer.Shininess = material->GetShininess();
|
||||
_cBuffer.Opacity = opacity;
|
||||
// Update the constant buffer
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &_cBuffer, 0, 0);
|
||||
_texture = material->GetTexture();
|
||||
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
|
||||
_deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
_deviceContext->DrawIndexed(static_cast<UINT>(_subMesh->GetIndexCount()), 0, 0);
|
||||
|
||||
// Turn back face culling back on in case another renderer
|
||||
// relies on it
|
||||
_deviceContext->RSSetState(_defaultRasteriserState.Get());
|
||||
}
|
||||
|
||||
void SubMeshRenderer::Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void SubMeshRenderer::BuildShaders()
|
||||
{
|
||||
DWORD shaderCompileFlags = 0;
|
||||
#if defined( _DEBUG )
|
||||
shaderCompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
ComPtr<ID3DBlob> compilationMessages = nullptr;
|
||||
|
||||
//Compile vertex shader
|
||||
HRESULT hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"VShader", "vs_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_vertexShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
// Even if there are no compiler messages, check to make sure there were no other errors.
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf()));
|
||||
|
||||
// Compile pixel shader
|
||||
hr = D3DCompileFromFile(L"TexturedShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"PShader", "ps_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_pixelShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreatePixelShader(_pixelShaderByteCode->GetBufferPointer(), _pixelShaderByteCode->GetBufferSize(), NULL, _pixelShader.GetAddressOf()));
|
||||
}
|
||||
|
||||
|
||||
void SubMeshRenderer::BuildVertexLayout()
|
||||
{
|
||||
// Create the vertex input layout. This tells DirectX the format
|
||||
// of each of the vertices we are sending to it.
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
ThrowIfFailed(_device->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc), _vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), _layout.GetAddressOf()));
|
||||
}
|
||||
|
||||
void SubMeshRenderer::BuildConstantBuffer()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = sizeof(CBUFFER);
|
||||
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void SubMeshRenderer::BuildBlendState()
|
||||
{
|
||||
D3D11_BLEND_DESC transparentDesc = { 0 };
|
||||
transparentDesc.AlphaToCoverageEnable = false;
|
||||
transparentDesc.IndependentBlendEnable = false;
|
||||
transparentDesc.RenderTarget[0].BlendEnable = true;
|
||||
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
ThrowIfFailed(_device->CreateBlendState(&transparentDesc, _transparentBlendState.GetAddressOf()));
|
||||
}
|
||||
|
||||
void SubMeshRenderer::BuildRendererState()
|
||||
{
|
||||
// Set default and no cull rasteriser states
|
||||
D3D11_RASTERIZER_DESC rasteriserDesc;
|
||||
rasteriserDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasteriserDesc.CullMode = D3D11_CULL_BACK;
|
||||
rasteriserDesc.FrontCounterClockwise = false;
|
||||
rasteriserDesc.DepthBias = 0;
|
||||
rasteriserDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasteriserDesc.DepthBiasClamp = 0.0f;
|
||||
rasteriserDesc.DepthClipEnable = true;
|
||||
rasteriserDesc.ScissorEnable = false;
|
||||
rasteriserDesc.MultisampleEnable = false;
|
||||
rasteriserDesc.AntialiasedLineEnable = false;
|
||||
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _defaultRasteriserState.GetAddressOf()));
|
||||
rasteriserDesc.CullMode = D3D11_CULL_NONE;
|
||||
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _noCullRasteriserState.GetAddressOf()));
|
||||
}
|
56
Graphics2/SubMeshRenderer.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "SharedMethods.h"
|
||||
#include "DirectXFramework.h"
|
||||
#include "Renderer.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
class SubMeshRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
void SetSubMesh(shared_ptr<SubMesh> subMesh);
|
||||
void SetWorldTransformation(FXMMATRIX worldTransformation);
|
||||
void SetAmbientLight(XMFLOAT4 ambientLight);
|
||||
void SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour);
|
||||
void SetCameraPosition(XMFLOAT4 cameraPosition);
|
||||
bool Initialise();
|
||||
void Render();
|
||||
void Shutdown(void);
|
||||
|
||||
private:
|
||||
shared_ptr<SubMesh> _subMesh;
|
||||
XMFLOAT4X4 _worldTransformation;
|
||||
XMFLOAT4 _ambientLight;
|
||||
XMFLOAT4 _directionalLightVector;
|
||||
XMFLOAT4 _directionalLightColour;
|
||||
XMFLOAT4 _cameraPosition;
|
||||
|
||||
ComPtr<ID3D11Device> _device;
|
||||
ComPtr<ID3D11DeviceContext> _deviceContext;
|
||||
|
||||
ComPtr<ID3D11Buffer> _vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> _indexBuffer;
|
||||
|
||||
ComPtr<ID3DBlob> _vertexShaderByteCode = nullptr;
|
||||
ComPtr<ID3DBlob> _pixelShaderByteCode = nullptr;
|
||||
ComPtr<ID3D11VertexShader> _vertexShader;
|
||||
ComPtr<ID3D11PixelShader> _pixelShader;
|
||||
ComPtr<ID3D11InputLayout> _layout;
|
||||
ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _texture;;
|
||||
|
||||
ComPtr<ID3D11BlendState> _transparentBlendState;
|
||||
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _noCullRasteriserState;
|
||||
|
||||
CBUFFER _cBuffer;
|
||||
|
||||
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildBlendState();
|
||||
void BuildRendererState();
|
||||
};
|
||||
|
248
Graphics2/TexturedCubeNode.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
#include "TexturedCubeNode.h"
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
XMFLOAT3 Position;
|
||||
XMFLOAT3 Normal;
|
||||
XMFLOAT2 TextureCoordinate;
|
||||
};
|
||||
|
||||
struct CBUFFER
|
||||
{
|
||||
XMMATRIX CompleteTransformation;
|
||||
XMMATRIX WorldTransformation;
|
||||
XMVECTOR LightVector;
|
||||
XMFLOAT4 LightColour;
|
||||
XMFLOAT4 AmbientColour;
|
||||
};
|
||||
|
||||
bool TexturedCubeNode::Initialise()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
|
||||
if (_device.Get() == nullptr || _deviceContext.Get() == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildGeometryBuffers();
|
||||
BuildShaders();
|
||||
BuildVertexLayout();
|
||||
BuildConstantBuffer();
|
||||
BuildTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TexturedCubeNode::Render()
|
||||
{
|
||||
XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation();
|
||||
XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetViewTransformation();
|
||||
|
||||
// Calculate the world x view x projection transformation
|
||||
XMMATRIX completeTransformation = XMLoadFloat4x4(&_combinedWorldTransformation) * viewTransformation * projectionTransformation;
|
||||
|
||||
// Draw the first cube
|
||||
CBUFFER cBuffer;
|
||||
cBuffer.CompleteTransformation = completeTransformation;
|
||||
cBuffer.WorldTransformation = XMLoadFloat4x4(&_combinedWorldTransformation);
|
||||
cBuffer.AmbientColour = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
cBuffer.LightVector = XMVector4Normalize(XMVectorSet(0.0f, 1.0f, 1.0f, 0.0f));
|
||||
cBuffer.LightColour = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// Update the constant buffer
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0);
|
||||
|
||||
// Set the texture to be used by the pixel shader
|
||||
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
|
||||
|
||||
// Now render the cube
|
||||
UINT stride = sizeof(Vertex);
|
||||
UINT offset = 0;
|
||||
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
|
||||
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
_deviceContext->DrawIndexed(36, 0, 0);
|
||||
}
|
||||
|
||||
void TexturedCubeNode::Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TexturedCubeNode::BuildGeometryBuffers()
|
||||
{
|
||||
// Create vertex buffer
|
||||
Vertex vertices[] =
|
||||
{
|
||||
{ XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) }, // side 1
|
||||
{ XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
|
||||
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) }, // side 2
|
||||
{ XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
|
||||
{ XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) }, // side 3
|
||||
{ XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
|
||||
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) }, // side 4
|
||||
{ XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
|
||||
{ XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) }, // side 5
|
||||
{ XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
|
||||
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) }, // side 6
|
||||
{ XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) },
|
||||
{ XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) },
|
||||
{ XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) },
|
||||
};
|
||||
|
||||
// Setup the structure that specifies how big the vertex
|
||||
// buffer should be
|
||||
D3D11_BUFFER_DESC vertexBufferDescriptor;
|
||||
vertexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
vertexBufferDescriptor.ByteWidth = sizeof(Vertex) * 24;
|
||||
vertexBufferDescriptor.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexBufferDescriptor.CPUAccessFlags = 0;
|
||||
vertexBufferDescriptor.MiscFlags = 0;
|
||||
vertexBufferDescriptor.StructureByteStride = 0;
|
||||
|
||||
// Now set up a structure that tells DirectX where to get the
|
||||
// data for the vertices from
|
||||
D3D11_SUBRESOURCE_DATA vertexInitialisationData;
|
||||
vertexInitialisationData.pSysMem = &vertices;
|
||||
|
||||
// and create the vertex buffer
|
||||
ThrowIfFailed(_device->CreateBuffer(&vertexBufferDescriptor, &vertexInitialisationData, _vertexBuffer.GetAddressOf()));
|
||||
|
||||
// Create the index buffer
|
||||
UINT indices[] = {
|
||||
0, 1, 2, // side 1
|
||||
2, 1, 3,
|
||||
4, 5, 6, // side 2
|
||||
6, 5, 7,
|
||||
8, 9, 10, // side 3
|
||||
10, 9, 11,
|
||||
12, 13, 14, // side 4
|
||||
14, 13, 15,
|
||||
16, 17, 18, // side 5
|
||||
18, 17, 19,
|
||||
20, 21, 22, // side 6
|
||||
22, 21, 23,
|
||||
};
|
||||
|
||||
// Setup the structure that specifies how big the index
|
||||
// buffer should be
|
||||
D3D11_BUFFER_DESC indexBufferDescriptor;
|
||||
indexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
indexBufferDescriptor.ByteWidth = sizeof(UINT) * 36;
|
||||
indexBufferDescriptor.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexBufferDescriptor.CPUAccessFlags = 0;
|
||||
indexBufferDescriptor.MiscFlags = 0;
|
||||
indexBufferDescriptor.StructureByteStride = 0;
|
||||
|
||||
// Now set up a structure that tells DirectX where to get the
|
||||
// data for the indices from
|
||||
D3D11_SUBRESOURCE_DATA indexInitialisationData;
|
||||
indexInitialisationData.pSysMem = &indices;
|
||||
|
||||
// and create the index buffer
|
||||
ThrowIfFailed(_device->CreateBuffer(&indexBufferDescriptor, &indexInitialisationData, _indexBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void TexturedCubeNode::BuildShaders()
|
||||
{
|
||||
DWORD shaderCompileFlags = 0;
|
||||
#if defined( _DEBUG )
|
||||
shaderCompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
ComPtr<ID3DBlob> compilationMessages = nullptr;
|
||||
|
||||
//Compile vertex shader
|
||||
HRESULT hr = D3DCompileFromFile(L"shader.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"VS", "vs_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_vertexShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
// Even if there are no compiler messages, check to make sure there were no other errors.
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf()));
|
||||
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
|
||||
|
||||
// Compile pixel shader
|
||||
hr = D3DCompileFromFile(L"shader.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"PS", "ps_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
_pixelShaderByteCode.GetAddressOf(),
|
||||
compilationMessages.GetAddressOf());
|
||||
|
||||
if (compilationMessages.Get() != nullptr)
|
||||
{
|
||||
// If there were any compilation messages, display them
|
||||
MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0);
|
||||
}
|
||||
ThrowIfFailed(hr);
|
||||
ThrowIfFailed(_device->CreatePixelShader(_pixelShaderByteCode->GetBufferPointer(), _pixelShaderByteCode->GetBufferSize(), NULL, _pixelShader.GetAddressOf()));
|
||||
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void TexturedCubeNode::BuildVertexLayout()
|
||||
{
|
||||
// Create the vertex input layout. This tells DirectX the format
|
||||
// of each of the vertices we are sending to it.
|
||||
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
|
||||
{
|
||||
{ "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 }
|
||||
};
|
||||
|
||||
ThrowIfFailed(_device->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc), _vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), _layout.GetAddressOf()));
|
||||
_deviceContext->IASetInputLayout(_layout.Get());
|
||||
}
|
||||
|
||||
void TexturedCubeNode::BuildConstantBuffer()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = sizeof(CBUFFER);
|
||||
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void TexturedCubeNode::BuildTexture()
|
||||
{
|
||||
// Note that in order to use CreateWICTextureFromFile, we
|
||||
// need to ensure we make a call to CoInitializeEx in our
|
||||
// Initialise method (and make the corresponding call to
|
||||
// CoUninitialize in the Shutdown method). Otherwise,
|
||||
// the following call will throw an exception
|
||||
ThrowIfFailed(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
_textureName.c_str(),
|
||||
nullptr,
|
||||
_texture.GetAddressOf()
|
||||
));
|
||||
}
|
39
Graphics2/TexturedCubeNode.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "SceneNode.h"
|
||||
#include "WICTextureLoader.h"
|
||||
#include "DirectXFramework.h"
|
||||
|
||||
class TexturedCubeNode : public SceneNode
|
||||
{
|
||||
public:
|
||||
TexturedCubeNode(wstring name, wstring textureName) : SceneNode(name) { _textureName = textureName; }
|
||||
|
||||
bool Initialise(void);
|
||||
void Render(void);
|
||||
void Shutdown(void);
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Device> _device;
|
||||
ComPtr<ID3D11DeviceContext> _deviceContext;
|
||||
|
||||
ComPtr<ID3D11Buffer> _vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> _indexBuffer;
|
||||
|
||||
ComPtr<ID3DBlob> _vertexShaderByteCode = nullptr;
|
||||
ComPtr<ID3DBlob> _pixelShaderByteCode = nullptr;
|
||||
ComPtr<ID3D11VertexShader> _vertexShader;
|
||||
ComPtr<ID3D11PixelShader> _pixelShader;
|
||||
ComPtr<ID3D11InputLayout> _layout;
|
||||
ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _texture;
|
||||
|
||||
wstring _textureName;
|
||||
|
||||
void BuildGeometryBuffers();
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildTexture();
|
||||
};
|
||||
|
70
Graphics2/TexturedShaders.hlsl
Normal file
@ -0,0 +1,70 @@
|
||||
cbuffer ConstantBuffer
|
||||
{
|
||||
float4x4 completeTransformation;
|
||||
float4x4 worldTransformation;
|
||||
float4 cameraPosition;
|
||||
float4 lightVector; // the light's vector
|
||||
float4 lightColor; // the light's color
|
||||
float4 ambientColor; // the ambient light's color
|
||||
float4 diffuseCoefficient; // The diffuse reflection cooefficient
|
||||
float4 specularCoefficient; // The specular reflection cooefficient
|
||||
float shininess; // The shininess factor
|
||||
float opacity; // The opacity (transparency) of the material. 0 = fully transparent, 1 = fully opaque
|
||||
float2 padding;
|
||||
}
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState ss;
|
||||
|
||||
struct VertexShaderInput
|
||||
{
|
||||
float3 Position : POSITION;
|
||||
float3 Normal : NORMAL;
|
||||
float2 TexCoord : TEXCOORD;
|
||||
};
|
||||
|
||||
struct PixelShaderInput
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float4 PositionWS: TEXCOORD1;
|
||||
float4 NormalWS : TEXCOORD2;
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
PixelShaderInput VShader(VertexShaderInput vin)
|
||||
{
|
||||
PixelShaderInput output;
|
||||
|
||||
output.Position = mul(completeTransformation, float4(vin.Position, 1.0f));
|
||||
output.PositionWS = mul(worldTransformation, float4(vin.Position, 1.0f));
|
||||
output.NormalWS = float4(mul((float3x3)worldTransformation, vin.Normal), 1.0f);
|
||||
output.TexCoord = vin.TexCoord;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 PShader(PixelShaderInput input) : SV_TARGET
|
||||
{
|
||||
float4 viewDirection = normalize(cameraPosition - input.PositionWS);
|
||||
float4 directionToLight = normalize(-lightVector);
|
||||
|
||||
// Calculate diffuse lighting
|
||||
float4 adjustedNormal = normalize(input.NormalWS);
|
||||
float NdotL = max(0, dot(adjustedNormal, directionToLight));
|
||||
float4 diffuse = saturate(lightColor * NdotL * diffuseCoefficient);
|
||||
|
||||
// Calculate specular component
|
||||
float4 R = 2 * NdotL * adjustedNormal - directionToLight;
|
||||
float RdotV = max(0, dot(R, viewDirection));
|
||||
float4 specular = saturate(lightColor * pow(RdotV, shininess) * specularCoefficient);
|
||||
|
||||
// Calculate ambient lighting
|
||||
float4 ambientLight = ambientColor * diffuseCoefficient;
|
||||
|
||||
// Combine all components
|
||||
float4 color = saturate((ambientLight + diffuse + specular) * Texture.Sample(ss, input.TexCoord));
|
||||
if (opacity < 1.0f)
|
||||
{
|
||||
color.a = opacity;
|
||||
}
|
||||
return color;
|
||||
}
|
BIN
Graphics2/Textures/Bricks.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
Graphics2/Textures/Concrete.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
Graphics2/Textures/Wood.png
Normal file
After Width: | Height: | Size: 293 KiB |
BIN
Graphics2/Textures/white.png
Normal file
After Width: | Height: | Size: 160 B |
BIN
Graphics2/Textures/woodbox.bmp
Normal file
After Width: | Height: | Size: 192 KiB |
934
Graphics2/WICTextureLoader.cpp
Normal file
@ -0,0 +1,934 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// We could load multi-frame images (TIFF/GIF) into a texture array.
|
||||
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
|
||||
|
||||
#include "WICTextureLoader.h"
|
||||
|
||||
#include <dxgiformat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <wincodec.h>
|
||||
|
||||
#include <wrl\client.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
|
||||
#pragma comment(lib,"dxguid.lib")
|
||||
#endif
|
||||
|
||||
using namespace DirectX;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace
|
||||
{
|
||||
//--------------------------------------------------------------------------------------
|
||||
template<UINT TNameLength>
|
||||
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char(&name)[TNameLength])
|
||||
{
|
||||
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
|
||||
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(resource);
|
||||
UNREFERENCED_PARAMETER(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format Translation Data
|
||||
//-------------------------------------------------------------------------------------
|
||||
struct WICTranslate
|
||||
{
|
||||
GUID wic;
|
||||
DXGI_FORMAT format;
|
||||
};
|
||||
|
||||
const WICTranslate g_WICFormats[] =
|
||||
{
|
||||
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
|
||||
|
||||
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
|
||||
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
|
||||
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
|
||||
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
|
||||
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
|
||||
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
|
||||
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format nearest conversion table
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
struct WICConvert
|
||||
{
|
||||
GUID source;
|
||||
GUID target;
|
||||
};
|
||||
|
||||
const WICConvert g_WICConvert[] =
|
||||
{
|
||||
// Note target GUID in this conversion table must be one of those directly supported formats (above).
|
||||
|
||||
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
|
||||
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
|
||||
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
|
||||
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
#endif
|
||||
|
||||
// We don't support n-channel formats
|
||||
};
|
||||
|
||||
bool g_WIC2 = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
IWICImagingFactory* _GetWIC()
|
||||
{
|
||||
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
IWICImagingFactory* factory = nullptr;
|
||||
InitOnceExecuteOnce(&s_initOnce,
|
||||
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory2,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory2),
|
||||
factory
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
|
||||
g_WIC2 = true;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory1,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
factory
|
||||
);
|
||||
return SUCCEEDED(hr) ? TRUE : FALSE;
|
||||
}
|
||||
#else
|
||||
return SUCCEEDED(CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
factory)) ? TRUE : FALSE;
|
||||
#endif
|
||||
}, nullptr, reinterpret_cast<LPVOID*>(&factory));
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
DXGI_FORMAT _WICToDXGI(const GUID& guid)
|
||||
{
|
||||
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
|
||||
{
|
||||
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
|
||||
return g_WICFormats[i].format;
|
||||
}
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
if (g_WIC2)
|
||||
{
|
||||
if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0)
|
||||
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
size_t _WICBitsPerPixel(REFGUID targetGuid)
|
||||
{
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return 0;
|
||||
|
||||
ComPtr<IWICComponentInfo> cinfo;
|
||||
if (FAILED(pWIC->CreateComponentInfo(targetGuid, cinfo.GetAddressOf())))
|
||||
return 0;
|
||||
|
||||
WICComponentType type;
|
||||
if (FAILED(cinfo->GetComponentType(&type)))
|
||||
return 0;
|
||||
|
||||
if (type != WICPixelFormat)
|
||||
return 0;
|
||||
|
||||
ComPtr<IWICPixelFormatInfo> pfinfo;
|
||||
if (FAILED(cinfo.As(&pfinfo)))
|
||||
return 0;
|
||||
|
||||
UINT bpp;
|
||||
if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
|
||||
return 0;
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
return DXGI_FORMAT_BC1_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_BC2_UNORM:
|
||||
return DXGI_FORMAT_BC2_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
return DXGI_FORMAT_BC3_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
return DXGI_FORMAT_BC7_UNORM_SRGB;
|
||||
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_ IWICBitmapFrameDecode *frame,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
UINT width, height;
|
||||
HRESULT hr = frame->GetSize(&width, &height);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
assert(width > 0 && height > 0);
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
// This is a bit conservative because the hardware could support larger textures than
|
||||
// the Feature Level defined minimums, but doing it this way is much easier and more
|
||||
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
|
||||
|
||||
switch (d3dDevice->GetFeatureLevel())
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
default:
|
||||
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(maxsize > 0);
|
||||
|
||||
UINT twidth, theight;
|
||||
if (width > maxsize || height > maxsize)
|
||||
{
|
||||
float ar = static_cast<float>(height) / static_cast<float>(width);
|
||||
if (width > height)
|
||||
{
|
||||
twidth = static_cast<UINT>(maxsize);
|
||||
theight = std::max<UINT>(1, static_cast<UINT>(static_cast<float>(maxsize) * ar));
|
||||
}
|
||||
else
|
||||
{
|
||||
theight = static_cast<UINT>(maxsize);
|
||||
twidth = std::max<UINT>(1, static_cast<UINT>(static_cast<float>(maxsize) / ar));
|
||||
}
|
||||
assert(twidth <= maxsize && theight <= maxsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
twidth = width;
|
||||
theight = height;
|
||||
}
|
||||
|
||||
// Determine format
|
||||
WICPixelFormatGUID pixelFormat;
|
||||
hr = frame->GetPixelFormat(&pixelFormat);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID convertGUID;
|
||||
memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID));
|
||||
|
||||
size_t bpp = 0;
|
||||
|
||||
DXGI_FORMAT format = _WICToDXGI(pixelFormat);
|
||||
if (format == DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (memcmp(&GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
if (g_WIC2)
|
||||
{
|
||||
memcpy(&convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID));
|
||||
format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
bpp = 96;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
memcpy(&convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID));
|
||||
format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
bpp = 128;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < _countof(g_WICConvert); ++i)
|
||||
{
|
||||
if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
|
||||
{
|
||||
memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID));
|
||||
|
||||
format = _WICToDXGI(g_WICConvert[i].target);
|
||||
assert(format != DXGI_FORMAT_UNKNOWN);
|
||||
bpp = _WICBitsPerPixel(convertGUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format == DXGI_FORMAT_UNKNOWN)
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
bpp = _WICBitsPerPixel(pixelFormat);
|
||||
}
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
if ((format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0)
|
||||
{
|
||||
// Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT
|
||||
UINT fmtSupport = 0;
|
||||
hr = d3dDevice->CheckFormatSupport(DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport);
|
||||
if (FAILED(hr) || !(fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
|
||||
{
|
||||
// Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up
|
||||
memcpy(&convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID));
|
||||
format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
bpp = 128;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bpp)
|
||||
return E_FAIL;
|
||||
|
||||
// Handle sRGB formats
|
||||
if (loadFlags & WIC_LOADER_FORCE_SRGB)
|
||||
{
|
||||
format = MakeSRGB(format);
|
||||
}
|
||||
else if (!(loadFlags & WIC_LOADER_IGNORE_SRGB))
|
||||
{
|
||||
ComPtr<IWICMetadataQueryReader> metareader;
|
||||
if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf())))
|
||||
{
|
||||
GUID containerFormat;
|
||||
if (SUCCEEDED(metareader->GetContainerFormat(&containerFormat)))
|
||||
{
|
||||
// Check for sRGB colorspace metadata
|
||||
bool sRGB = false;
|
||||
|
||||
PROPVARIANT value;
|
||||
PropVariantInit(&value);
|
||||
|
||||
if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0)
|
||||
{
|
||||
// Check for sRGB chunk
|
||||
if (SUCCEEDED(metareader->GetMetadataByName(L"/sRGB/RenderingIntent", &value)) && value.vt == VT_UI1)
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
}
|
||||
else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1)
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
|
||||
(void)PropVariantClear(&value);
|
||||
|
||||
if (sRGB)
|
||||
format = MakeSRGB(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify our target format is supported by the current device
|
||||
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
|
||||
UINT support = 0;
|
||||
hr = d3dDevice->CheckFormatSupport(format, &support);
|
||||
if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
|
||||
{
|
||||
// Fallback to RGBA 32-bit format which is supported by all devices
|
||||
memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID));
|
||||
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bpp = 32;
|
||||
}
|
||||
|
||||
// Allocate temporary memory for image
|
||||
size_t rowPitch = (twidth * bpp + 7) / 8;
|
||||
size_t imageSize = rowPitch * theight;
|
||||
|
||||
std::unique_ptr<uint8_t[]> temp(new (std::nothrow) uint8_t[imageSize]);
|
||||
if (!temp)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
// Load image data
|
||||
if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
|
||||
&& twidth == width
|
||||
&& theight == height)
|
||||
{
|
||||
// No format conversion or resize needed
|
||||
hr = frame->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else if (twidth != width || theight != height)
|
||||
{
|
||||
// Resize
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICBitmapScaler> scaler;
|
||||
hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID pfScaler;
|
||||
hr = scaler->GetPixelFormat(&pfScaler);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
|
||||
{
|
||||
// No format conversion needed
|
||||
hr = scaler->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComPtr<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
BOOL canConvert = FALSE;
|
||||
hr = FC->CanConvert(pfScaler, convertGUID, &canConvert);
|
||||
if (FAILED(hr) || !canConvert)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Format conversion but no resize
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
BOOL canConvert = FALSE;
|
||||
hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert);
|
||||
if (FAILED(hr) || !canConvert)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
// See if format is supported for auto-gen mipmaps (varies by feature level)
|
||||
bool autogen = false;
|
||||
if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
|
||||
{
|
||||
UINT fmtSupport = 0;
|
||||
hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
|
||||
if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
|
||||
{
|
||||
autogen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = twidth;
|
||||
desc.Height = theight;
|
||||
desc.MipLevels = (autogen) ? 0 : 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = usage;
|
||||
desc.CPUAccessFlags = cpuAccessFlags;
|
||||
|
||||
if (autogen)
|
||||
{
|
||||
desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET;
|
||||
desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.BindFlags = bindFlags;
|
||||
desc.MiscFlags = miscFlags;
|
||||
}
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = temp.get();
|
||||
initData.SysMemPitch = static_cast<UINT>(rowPitch);
|
||||
initData.SysMemSlicePitch = static_cast<UINT>(imageSize);
|
||||
|
||||
ID3D11Texture2D* tex = nullptr;
|
||||
hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex);
|
||||
if (SUCCEEDED(hr) && tex != 0)
|
||||
{
|
||||
if (textureView != 0)
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};
|
||||
SRVDesc.Format = desc.Format;
|
||||
|
||||
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
|
||||
|
||||
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
tex->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (autogen)
|
||||
{
|
||||
assert(d3dContext != 0);
|
||||
d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize));
|
||||
d3dContext->GenerateMips(*textureView);
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != 0)
|
||||
{
|
||||
*texture = tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetDebugObjectName(tex, "WICTextureLoader");
|
||||
tex->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromMemory(ID3D11Device* d3dDevice,
|
||||
const uint8_t* wicData,
|
||||
size_t wicDataSize,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView,
|
||||
size_t maxsize)
|
||||
{
|
||||
return CreateWICTextureFromMemoryEx(d3dDevice, nullptr, wicData, wicDataSize, maxsize,
|
||||
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromMemory(ID3D11Device* d3dDevice,
|
||||
ID3D11DeviceContext* d3dContext,
|
||||
const uint8_t* wicData,
|
||||
size_t wicDataSize,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView,
|
||||
size_t maxsize)
|
||||
{
|
||||
return CreateWICTextureFromMemoryEx(d3dDevice, d3dContext, wicData, wicDataSize, maxsize,
|
||||
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromMemoryEx(ID3D11Device* d3dDevice,
|
||||
const uint8_t* wicData,
|
||||
size_t wicDataSize,
|
||||
size_t maxsize,
|
||||
D3D11_USAGE usage,
|
||||
unsigned int bindFlags,
|
||||
unsigned int cpuAccessFlags,
|
||||
unsigned int miscFlags,
|
||||
unsigned int loadFlags,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
return CreateWICTextureFromMemoryEx(d3dDevice, nullptr, wicData, wicDataSize, maxsize,
|
||||
usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromMemoryEx(ID3D11Device* d3dDevice,
|
||||
ID3D11DeviceContext* d3dContext,
|
||||
const uint8_t* wicData,
|
||||
size_t wicDataSize,
|
||||
size_t maxsize,
|
||||
D3D11_USAGE usage,
|
||||
unsigned int bindFlags,
|
||||
unsigned int cpuAccessFlags,
|
||||
unsigned int miscFlags,
|
||||
unsigned int loadFlags,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
*texture = nullptr;
|
||||
}
|
||||
if (textureView)
|
||||
{
|
||||
*textureView = nullptr;
|
||||
}
|
||||
|
||||
if (!d3dDevice || !wicData || (!texture && !textureView))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!wicDataSize)
|
||||
return E_FAIL;
|
||||
|
||||
if (wicDataSize > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
|
||||
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Create input stream for memory
|
||||
ComPtr<IWICStream> stream;
|
||||
HRESULT hr = pWIC->CreateStream(stream.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Initialize WIC
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, frame.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), maxsize,
|
||||
usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
|
||||
texture, textureView);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
SetDebugObjectName(*texture, "WICTextureLoader");
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0)
|
||||
{
|
||||
SetDebugObjectName(*textureView, "WICTextureLoader");
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromFile(ID3D11Device* d3dDevice,
|
||||
const wchar_t* fileName,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView,
|
||||
size_t maxsize)
|
||||
{
|
||||
return CreateWICTextureFromFileEx(d3dDevice, nullptr, fileName, maxsize,
|
||||
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromFile(ID3D11Device* d3dDevice,
|
||||
ID3D11DeviceContext* d3dContext,
|
||||
const wchar_t* fileName,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView,
|
||||
size_t maxsize)
|
||||
{
|
||||
return CreateWICTextureFromFileEx(d3dDevice, d3dContext, fileName, maxsize,
|
||||
D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, WIC_LOADER_DEFAULT,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromFileEx(ID3D11Device* d3dDevice,
|
||||
const wchar_t* fileName,
|
||||
size_t maxsize,
|
||||
D3D11_USAGE usage,
|
||||
unsigned int bindFlags,
|
||||
unsigned int cpuAccessFlags,
|
||||
unsigned int miscFlags,
|
||||
unsigned int loadFlags,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
return CreateWICTextureFromFileEx(d3dDevice, nullptr, fileName, maxsize,
|
||||
usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
|
||||
texture, textureView);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromFileEx(ID3D11Device* d3dDevice,
|
||||
ID3D11DeviceContext* d3dContext,
|
||||
const wchar_t* fileName,
|
||||
size_t maxsize,
|
||||
D3D11_USAGE usage,
|
||||
unsigned int bindFlags,
|
||||
unsigned int cpuAccessFlags,
|
||||
unsigned int miscFlags,
|
||||
unsigned int loadFlags,
|
||||
ID3D11Resource** texture,
|
||||
ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
*texture = nullptr;
|
||||
}
|
||||
if (textureView)
|
||||
{
|
||||
*textureView = nullptr;
|
||||
}
|
||||
|
||||
if (!d3dDevice || !fileName || (!texture && !textureView))
|
||||
return E_INVALIDARG;
|
||||
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Initialize WIC
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, frame.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), maxsize,
|
||||
usage, bindFlags, cpuAccessFlags, miscFlags, loadFlags,
|
||||
texture, textureView);
|
||||
|
||||
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (texture != 0 || textureView != 0)
|
||||
{
|
||||
char strFileA[MAX_PATH];
|
||||
int result = WideCharToMultiByte(CP_ACP,
|
||||
WC_NO_BEST_FIT_CHARS,
|
||||
fileName,
|
||||
-1,
|
||||
strFileA,
|
||||
MAX_PATH,
|
||||
nullptr,
|
||||
FALSE
|
||||
);
|
||||
if (result > 0)
|
||||
{
|
||||
const char* pstrName = strrchr(strFileA, '\\');
|
||||
if (!pstrName)
|
||||
{
|
||||
pstrName = strFileA;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstrName++;
|
||||
}
|
||||
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0)
|
||||
{
|
||||
(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
130
Graphics2/WICTextureLoader.h
Normal file
@ -0,0 +1,130 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.h
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11_1.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
enum WIC_LOADER_FLAGS
|
||||
{
|
||||
WIC_LOADER_DEFAULT = 0,
|
||||
WIC_LOADER_FORCE_SRGB = 0x1,
|
||||
WIC_LOADER_IGNORE_SRGB = 0x2,
|
||||
};
|
||||
|
||||
// Standard version
|
||||
HRESULT CreateWICTextureFromMemory(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0);
|
||||
|
||||
HRESULT CreateWICTextureFromFile(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0);
|
||||
|
||||
// Standard version with optional auto-gen mipmap support
|
||||
HRESULT CreateWICTextureFromMemory(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0);
|
||||
|
||||
HRESULT CreateWICTextureFromFile(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0);
|
||||
|
||||
// Extended version
|
||||
HRESULT CreateWICTextureFromMemoryEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
|
||||
|
||||
HRESULT CreateWICTextureFromFileEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
|
||||
|
||||
// Extended version with optional auto-gen mipmap support
|
||||
HRESULT CreateWICTextureFromMemoryEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
|
||||
|
||||
HRESULT CreateWICTextureFromFileEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_opt_ ID3D11Resource** texture,
|
||||
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
|
||||
}
|
51
Graphics2/shader.hlsl
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
cbuffer ConstantBuffer
|
||||
{
|
||||
matrix worldViewProj; // The complete transformation
|
||||
matrix world; // The world transformation matrix
|
||||
float4 lightVector; // The directional light's vector
|
||||
float4 lightColour; // The directional light's colour
|
||||
float4 ambientColour; // The ambient light's colour
|
||||
};
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState ss;
|
||||
|
||||
struct VertexIn
|
||||
{
|
||||
float3 Position : POSITION;
|
||||
float3 Normal : NORMAL;
|
||||
float2 TexCoord : TEXCOORD;
|
||||
};
|
||||
|
||||
struct VertexOut
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float4 Colour : COLOUR;
|
||||
float2 TexCoord : TEXCOORD;
|
||||
};
|
||||
|
||||
VertexOut VS(VertexIn vin)
|
||||
{
|
||||
VertexOut vout;
|
||||
|
||||
// Transform to homogeneous clip space.
|
||||
vout.Position = mul(worldViewProj, float4(vin.Position, 1.0f));
|
||||
|
||||
// calculate the diffuse light and add it to the ambient light
|
||||
float4 vectorBackToLight = -lightVector;
|
||||
float4 adjustedNormal = normalize(mul(world, float4(vin.Normal, 1.0f)));
|
||||
float diffusebrightness = saturate(dot(adjustedNormal, vectorBackToLight));
|
||||
vout.Colour = saturate(ambientColour + lightColour * diffusebrightness);
|
||||
|
||||
vout.TexCoord = vin.TexCoord;
|
||||
|
||||
return vout;
|
||||
}
|
||||
|
||||
float4 PS(VertexOut pin) : SV_Target
|
||||
{
|
||||
return pin.Colour * Texture.Sample(ss, pin.TexCoord);
|
||||
}
|
||||
|
||||
|
79
Graphics2/treeTest.txt
Normal file
@ -0,0 +1,79 @@
|
||||
<3DSRoot>
|
||||
- Raytheon A
|
||||
-- UC
|
||||
--- LUC
|
||||
---- hub
|
||||
---- nuc1
|
||||
---- nuc2
|
||||
---- door
|
||||
---- tyre
|
||||
--- RUC
|
||||
---- hub1
|
||||
---- nuc11
|
||||
---- nuc21
|
||||
---- door1
|
||||
---- tyre1
|
||||
--- NUC
|
||||
---- ndoor1
|
||||
---- tyre2
|
||||
---- hub2
|
||||
---- nuc22
|
||||
---- nuc12
|
||||
---- ndoor
|
||||
-- Fus
|
||||
--- mast1
|
||||
--- intakes
|
||||
--- glaze2
|
||||
--- exhausts
|
||||
--- gill
|
||||
--- glaze
|
||||
--- ndoor2
|
||||
--- grill
|
||||
--- fin
|
||||
--- nose
|
||||
--- mast11
|
||||
--- fus
|
||||
--- boxin
|
||||
--- cockpit
|
||||
---- recline2
|
||||
---- recline1
|
||||
---- floor
|
||||
---- comb
|
||||
---- pedals
|
||||
---- column
|
||||
---- compass
|
||||
---- rests
|
||||
---- cushion1
|
||||
---- rests1
|
||||
---- back
|
||||
---- cushoid
|
||||
---- rest
|
||||
---- recline
|
||||
---- cushion
|
||||
---- mount
|
||||
---- back1
|
||||
---- cushoid1
|
||||
---- rest1
|
||||
---- siupon1
|
||||
---- siupon
|
||||
---- recline3
|
||||
---- mount1
|
||||
---- cushion2
|
||||
---- rests2
|
||||
---- cushion3
|
||||
---- rests3
|
||||
---- panel
|
||||
---- infus
|
||||
--- airscrew
|
||||
---- prop
|
||||
---- prop1
|
||||
---- prop2
|
||||
---- spinner
|
||||
--- tlamp
|
||||
--- bumper
|
||||
-- tail
|
||||
--- tail1
|
||||
--- tail0
|
||||
-- wing
|
||||
--- wing1
|
||||
--- wing0
|