Added the ASSIMP library

Added the files provided for the tutorial
Added the SplitMeshNode and SubMeshNode classes
This commit is contained in:
iDunnoDev
2022-03-18 21:26:31 +00:00
committed by iDunnoDev
parent 6bdfe4569f
commit 65255f1321
105 changed files with 19816 additions and 11 deletions

View File

@ -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();

View File

@ -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;
};

View File

@ -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;
}
}

View File

@ -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;
};

View File

@ -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">

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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);
};

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

13
Graphics2/Renderer.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
class Renderer
{
public:
Renderer() {}
virtual ~Renderer() {}
virtual bool Initialise() = 0;
virtual void Render() = 0;
virtual void Shutdown() {};
};

View 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;
}

View 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
View 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;
}

View File

@ -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
View File

View 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;
};

View 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
View 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);
};

View 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
View 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
View 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
View 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;
};

View 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()));
}

View 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();
};

View 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()
));
}

View 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();
};

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
Graphics2/Textures/Wood.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View 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;
}

View 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
View 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
View 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