summaryrefslogtreecommitdiff
path: root/libs/assimp/samples/SimpleTexturedDirectx11
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
committersanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
commitdb81b925d776103326128bf629cbdda576a223e7 (patch)
tree58bea8155c686733310009f6bed7363f91fbeb9d /libs/assimp/samples/SimpleTexturedDirectx11
parent55860037b14fb3893ba21cf2654c83d349cc1082 (diff)
move 3rd-party librarys into libs/ and add built-in honeysuckle
Diffstat (limited to 'libs/assimp/samples/SimpleTexturedDirectx11')
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/CMakeLists.txt51
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h107
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp186
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h42
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl9
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp57
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp697
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h61
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl23
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp599
10 files changed, 1832 insertions, 0 deletions
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/CMakeLists.txt b/libs/assimp/samples/SimpleTexturedDirectx11/CMakeLists.txt
new file mode 100644
index 0000000..007ada3
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/CMakeLists.txt
@@ -0,0 +1,51 @@
+FIND_PACKAGE(DirectX)
+
+IF ( MSVC )
+ SET(M_LIB)
+ENDIF ()
+
+if ( MSVC )
+ ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+ ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+ REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
+endif ()
+
+ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/")
+
+INCLUDE_DIRECTORIES(
+ ${Assimp_SOURCE_DIR}/include
+ ${Assimp_SOURCE_DIR}/code
+ ${SAMPLES_SHARED_CODE_DIR}
+)
+
+LINK_DIRECTORIES(
+ ${Assimp_BINARY_DIR}
+ ${Assimp_BINARY_DIR}/lib
+)
+
+ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32
+ SimpleTexturedDirectx11/Mesh.h
+ SimpleTexturedDirectx11/ModelLoader.cpp
+ SimpleTexturedDirectx11/ModelLoader.h
+ #SimpleTexturedDirectx11/PixelShader.hlsl
+ SimpleTexturedDirectx11/TextureLoader.cpp
+ SimpleTexturedDirectx11/TextureLoader.h
+ #SimpleTexturedDirectx11/VertexShader.hlsl
+ SimpleTexturedDirectx11/main.cpp
+ SimpleTexturedDirectx11/SafeRelease.hpp
+ ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
+ ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
+)
+
+TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp_simpletextureddirectx11)
+
+SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
+
+TARGET_LINK_LIBRARIES( assimp_simpletextureddirectx11 assimp comctl32.lib winmm.lib )
+SET_TARGET_PROPERTIES( assimp_simpletextureddirectx11 PROPERTIES
+ OUTPUT_NAME assimp_simpletextureddirectx11
+)
+
+INSTALL( TARGETS assimp_simpletextureddirectx11
+ DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
+)
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
new file mode 100644
index 0000000..e0169ee
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
@@ -0,0 +1,107 @@
+#ifndef MESH_H
+#define MESH_H
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <vector>
+#include <stdexcept>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+
+using namespace DirectX;
+
+#include "SafeRelease.hpp"
+
+struct VERTEX {
+ FLOAT X, Y, Z;
+ XMFLOAT2 texcoord;
+};
+
+struct Texture {
+ std::string type;
+ std::string path;
+ ID3D11ShaderResourceView *texture;
+
+ void Release() {
+ SafeRelease(texture);
+ }
+};
+
+class Mesh {
+public:
+ std::vector<VERTEX> vertices_;
+ std::vector<UINT> indices_;
+ std::vector<Texture> textures_;
+ ID3D11Device *dev_;
+
+ Mesh(ID3D11Device *dev, const std::vector<VERTEX>& vertices, const std::vector<UINT>& indices, const std::vector<Texture>& textures) :
+ vertices_(vertices),
+ indices_(indices),
+ textures_(textures),
+ dev_(dev),
+ VertexBuffer_(nullptr),
+ IndexBuffer_(nullptr) {
+ this->setupMesh(this->dev_);
+ }
+
+ void Draw(ID3D11DeviceContext *devcon) {
+ UINT stride = sizeof(VERTEX);
+ UINT offset = 0;
+
+ devcon->IASetVertexBuffers(0, 1, &VertexBuffer_, &stride, &offset);
+ devcon->IASetIndexBuffer(IndexBuffer_, DXGI_FORMAT_R32_UINT, 0);
+
+ devcon->PSSetShaderResources(0, 1, &textures_[0].texture);
+
+ devcon->DrawIndexed(static_cast<UINT>(indices_.size()), 0, 0);
+ }
+
+ void Close() {
+ SafeRelease(VertexBuffer_);
+ SafeRelease(IndexBuffer_);
+ }
+private:
+ // Render data
+ ID3D11Buffer *VertexBuffer_, *IndexBuffer_;
+
+ // Functions
+ // Initializes all the buffer objects/arrays
+ void setupMesh(ID3D11Device *dev) {
+ HRESULT hr;
+
+ D3D11_BUFFER_DESC vbd;
+ vbd.Usage = D3D11_USAGE_IMMUTABLE;
+ vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices_.size());
+ vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbd.CPUAccessFlags = 0;
+ vbd.MiscFlags = 0;
+
+ D3D11_SUBRESOURCE_DATA initData;
+ initData.pSysMem = &vertices_[0];
+
+ hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer_);
+ if (FAILED(hr)) {
+ Close();
+ throw std::runtime_error("Failed to create vertex buffer.");
+ }
+
+ D3D11_BUFFER_DESC ibd;
+ ibd.Usage = D3D11_USAGE_IMMUTABLE;
+ ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices_.size());
+ ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ ibd.CPUAccessFlags = 0;
+ ibd.MiscFlags = 0;
+
+ initData.pSysMem = &indices_[0];
+
+ hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer_);
+ if (FAILED(hr)) {
+ Close();
+ throw std::runtime_error("Failed to create index buffer.");
+ }
+ }
+};
+
+#endif
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
new file mode 100644
index 0000000..18bb10f
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
@@ -0,0 +1,186 @@
+#include "ModelLoader.h"
+
+ModelLoader::ModelLoader() :
+ dev_(nullptr),
+ devcon_(nullptr),
+ meshes_(),
+ directory_(),
+ textures_loaded_(),
+ hwnd_(nullptr) {
+ // empty
+}
+
+
+ModelLoader::~ModelLoader() {
+ // empty
+}
+
+bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) {
+ Assimp::Importer importer;
+
+ const aiScene* pScene = importer.ReadFile(filename,
+ aiProcess_Triangulate |
+ aiProcess_ConvertToLeftHanded);
+
+ if (pScene == nullptr)
+ return false;
+
+ this->directory_ = filename.substr(0, filename.find_last_of("/\\"));
+
+ this->dev_ = dev;
+ this->devcon_ = devcon;
+ this->hwnd_ = hwnd;
+
+ processNode(pScene->mRootNode, pScene);
+
+ return true;
+}
+
+void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
+ for (size_t i = 0; i < meshes_.size(); ++i ) {
+ meshes_[i].Draw(devcon);
+ }
+}
+
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
+ // Data to fill
+ std::vector<VERTEX> vertices;
+ std::vector<UINT> indices;
+ std::vector<Texture> textures;
+
+ // Walk through each of the mesh's vertices
+ for (UINT i = 0; i < mesh->mNumVertices; i++) {
+ VERTEX vertex;
+
+ vertex.X = mesh->mVertices[i].x;
+ vertex.Y = mesh->mVertices[i].y;
+ vertex.Z = mesh->mVertices[i].z;
+
+ if (mesh->mTextureCoords[0]) {
+ vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
+ vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
+ }
+
+ vertices.push_back(vertex);
+ }
+
+ for (UINT i = 0; i < mesh->mNumFaces; i++) {
+ aiFace face = mesh->mFaces[i];
+
+ for (UINT j = 0; j < face.mNumIndices; j++)
+ indices.push_back(face.mIndices[j]);
+ }
+
+ if (mesh->mMaterialIndex >= 0) {
+ aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
+
+ std::vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
+ textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
+ }
+
+ return Mesh(dev_, vertices, indices, textures);
+}
+
+std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
+ std::vector<Texture> textures;
+ for (UINT i = 0; i < mat->GetTextureCount(type); i++) {
+ aiString str;
+ mat->GetTexture(type, i, &str);
+ // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
+ bool skip = false;
+ for (UINT j = 0; j < textures_loaded_.size(); j++) {
+ if (std::strcmp(textures_loaded_[j].path.c_str(), str.C_Str()) == 0) {
+ textures.push_back(textures_loaded_[j]);
+ skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
+ break;
+ }
+ }
+ if (!skip) { // If texture hasn't been loaded already, load it
+ HRESULT hr;
+ Texture texture;
+
+ const aiTexture* embeddedTexture = scene->GetEmbeddedTexture(str.C_Str());
+ if (embeddedTexture != nullptr) {
+ texture.texture = loadEmbeddedTexture(embeddedTexture);
+ } else {
+ std::string filename = std::string(str.C_Str());
+ filename = directory_ + '/' + filename;
+ std::wstring filenamews = std::wstring(filename.begin(), filename.end());
+ hr = CreateWICTextureFromFile(dev_, devcon_, filenamews.c_str(), nullptr, &texture.texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
+ }
+ texture.type = typeName;
+ texture.path = str.C_Str();
+ textures.push_back(texture);
+ this->textures_loaded_.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
+ }
+ }
+ return textures;
+}
+
+void ModelLoader::Close() {
+ for (auto& t : textures_loaded_)
+ t.Release();
+
+ for (size_t i = 0; i < meshes_.size(); i++) {
+ meshes_[i].Close();
+ }
+}
+
+void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
+ for (UINT i = 0; i < node->mNumMeshes; i++) {
+ aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
+ meshes_.push_back(this->processMesh(mesh, scene));
+ }
+
+ for (UINT i = 0; i < node->mNumChildren; i++) {
+ this->processNode(node->mChildren[i], scene);
+ }
+}
+
+ID3D11ShaderResourceView * ModelLoader::loadEmbeddedTexture(const aiTexture* embeddedTexture) {
+ HRESULT hr;
+ ID3D11ShaderResourceView *texture = nullptr;
+
+ if (embeddedTexture->mHeight != 0) {
+ // Load an uncompressed ARGB8888 embedded texture
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = embeddedTexture->mWidth;
+ desc.Height = embeddedTexture->mHeight;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ D3D11_SUBRESOURCE_DATA subresourceData;
+ subresourceData.pSysMem = embeddedTexture->pcData;
+ subresourceData.SysMemPitch = embeddedTexture->mWidth * 4;
+ subresourceData.SysMemSlicePitch = embeddedTexture->mWidth * embeddedTexture->mHeight * 4;
+
+ ID3D11Texture2D *texture2D = nullptr;
+ hr = dev_->CreateTexture2D(&desc, &subresourceData, &texture2D);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "CreateTexture2D failed!", "Error!", MB_ICONERROR | MB_OK);
+
+ hr = dev_->CreateShaderResourceView(texture2D, nullptr, &texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "CreateShaderResourceView failed!", "Error!", MB_ICONERROR | MB_OK);
+
+ return texture;
+ }
+
+ // mHeight is 0, so try to load a compressed texture of mWidth bytes
+ const size_t size = embeddedTexture->mWidth;
+
+ hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<const unsigned char*>(embeddedTexture->pcData), size, nullptr, &texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+
+ return texture;
+}
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h
new file mode 100644
index 0000000..a04484f
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h
@@ -0,0 +1,42 @@
+#ifndef MODEL_LOADER_H
+#define MODEL_LOADER_H
+
+#include <vector>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+
+#include <assimp\Importer.hpp>
+#include <assimp\scene.h>
+#include <assimp\postprocess.h>
+
+#include "Mesh.h"
+#include "TextureLoader.h"
+
+using namespace DirectX;
+
+class ModelLoader
+{
+public:
+ ModelLoader();
+ ~ModelLoader();
+
+ bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
+ void Draw(ID3D11DeviceContext* devcon);
+
+ void Close();
+private:
+ ID3D11Device *dev_;
+ ID3D11DeviceContext *devcon_;
+ std::vector<Mesh> meshes_;
+ std::string directory_;
+ std::vector<Texture> textures_loaded_;
+ HWND hwnd_;
+
+ void processNode(aiNode* node, const aiScene* scene);
+ Mesh processMesh(aiMesh* mesh, const aiScene* scene);
+ std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene);
+ ID3D11ShaderResourceView* loadEmbeddedTexture(const aiTexture* embeddedTexture);
+};
+
+#endif // !MODEL_LOADER_H
+
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl
new file mode 100644
index 0000000..cae4fa7
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl
@@ -0,0 +1,9 @@
+Texture2D diffTexture;
+SamplerState SampleType;
+
+float4 main(float4 pos : SV_POSITION, float2 texcoord : TEXCOORD) : SV_TARGET
+{
+ float4 textureColor = diffTexture.Sample(SampleType, texcoord);
+
+ return textureColor;
+} \ No newline at end of file
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp
new file mode 100644
index 0000000..2fd80db
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp
@@ -0,0 +1,57 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+/* Used to reduce to reduce the number of lines when calling Release()
+ on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE'
+ MACRO to ease debugging. */
+template<typename T>
+inline void SafeRelease(T*& x) {
+ if (x) {
+ x->Release();
+ x = nullptr;
+ }
+}
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp
new file mode 100644
index 0000000..a02c53c
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp
@@ -0,0 +1,697 @@
+//--------------------------------------------------------------------------------------
+// File: WICTextureLoader.cpp
+//
+// Function for loading a WIC image and creating a Direct3D 11 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 <dxgiformat.h>
+#include <assert.h>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#endif // _MSC_VER
+
+#include <wincodec.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#include <memory>
+
+#include "TextureLoader.h"
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
+#define DXGI_1_2_FORMATS
+#endif
+
+//---------------------------------------------------------------------------------
+template<class T> class ScopedObject
+{
+public:
+ explicit ScopedObject(T *p = 0) : _pointer(p) {}
+ ~ScopedObject()
+ {
+ if (_pointer)
+ {
+ _pointer->Release();
+ _pointer = nullptr;
+ }
+ }
+
+ bool IsNull() const { return (!_pointer); }
+
+ T& operator*() { return *_pointer; }
+ T* operator->() { return _pointer; }
+ T** operator&() { return &_pointer; }
+
+ void Reset(T *p = 0) { if (_pointer) { _pointer->Release(); } _pointer = p; }
+
+ T* Get() const { return _pointer; }
+
+private:
+ ScopedObject(const ScopedObject&);
+ ScopedObject& operator=(const ScopedObject&);
+
+ T* _pointer;
+};
+
+//-------------------------------------------------------------------------------------
+// WIC Pixel Format Translation Data
+//-------------------------------------------------------------------------------------
+struct WICTranslate
+{
+ GUID wic;
+ DXGI_FORMAT format;
+};
+
+static 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_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
+
+#ifdef DXGI_1_2_FORMATS
+
+ { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
+ { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
+
+#endif // DXGI_1_2_FORMATS
+
+ { 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 },
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+ { GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
+#endif
+};
+
+//-------------------------------------------------------------------------------------
+// WIC Pixel Format nearest conversion table
+//-------------------------------------------------------------------------------------
+
+struct WICConvert
+{
+ GUID source;
+ GUID target;
+};
+
+static 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
+
+#ifdef DXGI_1_2_FORMATS
+
+ { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
+
+#else
+
+ { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+
+#endif // DXGI_1_2_FORMATS
+
+ { 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_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_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_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+ { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+ { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+ { 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
+};
+
+//--------------------------------------------------------------------------------------
+static IWICImagingFactory* _GetWIC()
+{
+ static IWICImagingFactory* s_Factory = nullptr;
+
+ if (s_Factory)
+ return s_Factory;
+
+ HRESULT hr = CoCreateInstance(
+ CLSID_WICImagingFactory,
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWICImagingFactory),
+ (LPVOID*)&s_Factory
+ );
+
+ if (FAILED(hr))
+ {
+ s_Factory = nullptr;
+ return nullptr;
+ }
+
+ return s_Factory;
+}
+
+//---------------------------------------------------------------------------------
+static 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;
+ }
+
+ return DXGI_FORMAT_UNKNOWN;
+}
+
+//---------------------------------------------------------------------------------
+static size_t _WICBitsPerPixel(REFGUID targetGuid)
+{
+ IWICImagingFactory* pWIC = _GetWIC();
+ if (!pWIC)
+ return 0;
+
+ ScopedObject<IWICComponentInfo> cinfo;
+ if (FAILED(pWIC->CreateComponentInfo(targetGuid, &cinfo)))
+ return 0;
+
+ WICComponentType type;
+ if (FAILED(cinfo->GetComponentType(&type)))
+ return 0;
+
+ if (type != WICPixelFormat)
+ return 0;
+
+ ScopedObject<IWICPixelFormatInfo> pfinfo;
+ if (FAILED(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>(&pfinfo))))
+ return 0;
+
+ UINT bpp;
+ if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
+ return 0;
+
+ return bpp;
+}
+
+//---------------------------------------------------------------------------------
+static HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
+ _In_opt_ ID3D11DeviceContext* d3dContext,
+ _In_ IWICBitmapFrameDecode *frame,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize)
+{
+ 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 = static_cast<UINT>(static_cast<float>(maxsize) * ar);
+ }
+ else
+ {
+ theight = static_cast<UINT>(maxsize);
+ twidth = 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)
+ {
+ 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 (!bpp)
+ return E_FAIL;
+
+ // 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 uint8_t[imageSize]);
+
+ // 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
+ IWICImagingFactory* pWIC = _GetWIC();
+ if (!pWIC)
+ return E_NOINTERFACE;
+
+ ScopedObject<IWICBitmapScaler> scaler;
+ hr = pWIC->CreateBitmapScaler(&scaler);
+ 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
+ {
+ ScopedObject<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter(&FC);
+ if (FAILED(hr))
+ return hr;
+
+ hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
+ 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
+ IWICImagingFactory* pWIC = _GetWIC();
+ if (!pWIC)
+ return E_NOINTERFACE;
+
+ ScopedObject<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter(&FC);
+ if (FAILED(hr))
+ return hr;
+
+ hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
+ 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 = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
+
+ 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;
+ memset(&SRVDesc, 0, sizeof(SRVDesc));
+ SRVDesc.Format = 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
+ {
+#if defined(_DEBUG) || defined(PROFILE)
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName,
+ sizeof("WICTextureLoader") - 1,
+ "WICTextureLoader"
+ );
+#endif
+ tex->Release();
+ }
+ }
+
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
+ _In_opt_ ID3D11DeviceContext* d3dContext,
+ _In_bytecount_(wicDataSize) const uint8_t* wicData,
+ _In_ size_t wicDataSize,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize
+)
+{
+ if (!d3dDevice || !wicData || (!texture && !textureView))
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!wicDataSize)
+ {
+ return E_FAIL;
+ }
+
+#ifdef _M_AMD64
+ if (wicDataSize > 0xFFFFFFFF)
+ return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
+#endif
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if (!pWIC)
+ return E_NOINTERFACE;
+
+ // Create input stream for memory
+ ScopedObject<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream(&stream);
+ if (FAILED(hr))
+ return hr;
+
+ hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
+ if (FAILED(hr))
+ return hr;
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder);
+ if (FAILED(hr))
+ return hr;
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame(0, &frame);
+ if (FAILED(hr))
+ return hr;
+
+ hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
+ if (FAILED(hr))
+ return hr;
+
+#if defined(_DEBUG) || defined(PROFILE)
+ if (texture != 0 && *texture != 0)
+ {
+ (*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
+ sizeof("WICTextureLoader") - 1,
+ "WICTextureLoader"
+ );
+ }
+
+ if (textureView != 0 && *textureView != 0)
+ {
+ (*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
+ sizeof("WICTextureLoader") - 1,
+ "WICTextureLoader"
+ );
+ }
+#endif
+
+ return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
+ _In_opt_ ID3D11DeviceContext* d3dContext,
+ _In_z_ const wchar_t* fileName,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize)
+{
+ if (!d3dDevice || !fileName || (!texture && !textureView))
+ {
+ return E_INVALIDARG;
+ }
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if (!pWIC)
+ return E_NOINTERFACE;
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
+ if (FAILED(hr))
+ return hr;
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame(0, &frame);
+ if (FAILED(hr))
+ return hr;
+
+ hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
+ if (FAILED(hr))
+ return hr;
+
+#if defined(_DEBUG) || defined(PROFILE)
+ if (texture != 0 || textureView != 0)
+ {
+ CHAR strFileA[MAX_PATH];
+ WideCharToMultiByte(CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ fileName,
+ -1,
+ strFileA,
+ MAX_PATH,
+ nullptr,
+ FALSE
+ );
+ 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;
+}
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h
new file mode 100644
index 0000000..5448daf
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h
@@ -0,0 +1,61 @@
+//--------------------------------------------------------------------------------------
+// File: WICTextureLoader.h
+//
+// Function for loading a WIC image and creating a Direct3D 11 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
+//--------------------------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <d3d11.h>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#endif // _MSC_VER
+
+#include <stdint.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
+ _In_opt_ ID3D11DeviceContext* d3dContext,
+ _In_bytecount_(wicDataSize) const uint8_t* wicData,
+ _In_ size_t wicDataSize,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize = 0
+);
+
+HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
+ _In_opt_ ID3D11DeviceContext* d3dContext,
+ _In_z_ const wchar_t* szFileName,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView** textureView,
+ _In_ size_t maxsize = 0
+);
+
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl
new file mode 100644
index 0000000..3330077
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl
@@ -0,0 +1,23 @@
+cbuffer ConstantBuffer : register(b0)
+{
+ matrix World;
+ matrix View;
+ matrix Projection;
+}
+
+struct VOut {
+ float4 pos : SV_POSITION;
+ float2 texcoord : TEXCOORD;
+};
+
+VOut main(float4 pos : POSITION, float2 texcoord : TEXCOORD)
+{
+ VOut output;
+
+ output.pos = mul(pos, World);
+ output.pos = mul(output.pos, View);
+ output.pos = mul(output.pos, Projection);
+ output.texcoord = texcoord;
+
+ return output;
+} \ No newline at end of file
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
new file mode 100644
index 0000000..f7b3502
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
@@ -0,0 +1,599 @@
+// ---------------------------------------------------------------------------
+// Simple Assimp Directx11 Sample
+// This is a very basic sample and only reads diffuse texture
+// but this can load both embedded textures in fbx and non-embedded textures
+//
+//
+// Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your
+// model name (line 480)
+// If your model isn't a fbx with embedded textures make sure your model's
+// textures are in same directory as your model
+//
+//
+// Written by IAS. :)
+// ---------------------------------------------------------------------------
+
+#include <Windows.h>
+#include <shellapi.h>
+#include <stdexcept>
+#include <windowsx.h>
+#include <d3d11_1.h>
+#include <dxgi1_2.h>
+#include <DirectXMath.h>
+#include <d3dcompiler.h>
+#include "ModelLoader.h"
+#include "UTFConverter.h"
+#include "SafeRelease.hpp"
+
+#ifdef _MSC_VER
+#pragma comment (lib, "d3d11.lib")
+#pragma comment (lib, "Dxgi.lib")
+#pragma comment(lib,"d3dcompiler.lib")
+#pragma comment (lib, "dxguid.lib")
+#endif // _MSC_VER
+
+using namespace DirectX;
+using namespace AssimpSamples::SharedCode;
+
+#define VERTEX_SHADER_FILE L"VertexShader.hlsl"
+#define PIXEL_SHADER_FILE L"PixelShader.hlsl"
+
+// ------------------------------------------------------------
+// Structs
+// ------------------------------------------------------------
+struct ConstantBuffer {
+ XMMATRIX mWorld;
+ XMMATRIX mView;
+ XMMATRIX mProjection;
+};
+
+// ------------------------------------------------------------
+// Window Variables
+// ------------------------------------------------------------
+#define SCREEN_WIDTH 800
+#define SCREEN_HEIGHT 600
+
+const char g_szClassName[] = "directxWindowClass";
+
+static std::string g_ModelPath;
+
+UINT width, height;
+HWND g_hwnd = nullptr;
+
+// ------------------------------------------------------------
+// DirectX Variables
+// ------------------------------------------------------------
+D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
+D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
+ID3D11Device *dev = nullptr;
+ID3D11Device1 *dev1 = nullptr;
+ID3D11DeviceContext *devcon = nullptr;
+ID3D11DeviceContext1 *devcon1 = nullptr;
+IDXGISwapChain *swapchain = nullptr;
+IDXGISwapChain1 *swapchain1 = nullptr;
+ID3D11RenderTargetView *backbuffer = nullptr;
+ID3D11VertexShader *pVS = nullptr;
+ID3D11PixelShader *pPS = nullptr;
+ID3D11InputLayout *pLayout = nullptr;
+ID3D11Buffer *pConstantBuffer = nullptr;
+ID3D11Texture2D *g_pDepthStencil = nullptr;
+ID3D11DepthStencilView *g_pDepthStencilView = nullptr;
+ID3D11SamplerState *TexSamplerState = nullptr;
+ID3D11RasterizerState *rasterstate = nullptr;
+ID3D11Debug* d3d11debug = nullptr;
+
+XMMATRIX m_World;
+XMMATRIX m_View;
+XMMATRIX m_Projection;
+
+// ------------------------------------------------------------
+// Function identifiers
+// ------------------------------------------------------------
+
+void InitD3D(HINSTANCE hinstance, HWND hWnd);
+void CleanD3D(void);
+void RenderFrame(void);
+
+void InitPipeline();
+void InitGraphics();
+
+HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob);
+void Throwanerror(LPCSTR errormessage);
+
+// ------------------------------------------------------------
+// Our Model
+// ------------------------------------------------------------
+
+ModelLoader *ourModel = nullptr;
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
+ LPWSTR /*lpCmdLine*/, int nCmdShow)
+{
+ int argc;
+ LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argv) {
+ MessageBox(nullptr,
+ TEXT("An error occurred while reading command line arguments."),
+ TEXT("Error!"),
+ MB_ICONERROR | MB_OK);
+ return EXIT_FAILURE;
+ }
+
+ // Free memory allocated from CommandLineToArgvW.
+ auto free_command_line_allocated_memory = [&argv]() {
+ if (argv) {
+ LocalFree(argv);
+ argv = nullptr;
+ }
+ };
+
+ // Ensure that a model file has been specified.
+ if (argc < 2) {
+ MessageBox(nullptr,
+ TEXT("No model file specified. The program will now close."),
+ TEXT("Error!"),
+ MB_ICONERROR | MB_OK);
+ free_command_line_allocated_memory();
+ return EXIT_FAILURE;
+ }
+
+ // Retrieve the model file path.
+ g_ModelPath = UTFConverter(argv[1]).str();
+
+ free_command_line_allocated_memory();
+
+ WNDCLASSEX wc;
+ MSG msg;
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = 0;
+ wc.lpfnWndProc = WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wc.hbrBackground = nullptr;
+ wc.lpszMenuName = nullptr;
+ wc.lpszClassName = g_szClassName;
+ wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
+
+ if (!RegisterClassEx(&wc))
+ {
+ MessageBox(nullptr, "Window Registration Failed!", "Error!",
+ MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
+ AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+
+ g_hwnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ g_szClassName,
+ " Simple Textured Directx11 Sample ",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
+ nullptr, nullptr, hInstance, nullptr
+ );
+
+ if (g_hwnd == nullptr)
+ {
+ MessageBox(nullptr, "Window Creation Failed!", "Error!",
+ MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ ShowWindow(g_hwnd, nCmdShow);
+ UpdateWindow(g_hwnd);
+
+ width = wr.right - wr.left;
+ height = wr.bottom - wr.top;
+
+ try {
+ InitD3D(hInstance, g_hwnd);
+
+ while (true)
+ {
+
+ if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ if (msg.message == WM_QUIT)
+ break;
+ }
+
+ RenderFrame();
+ }
+
+ CleanD3D();
+ return static_cast<int>(msg.wParam);
+ } catch (const std::exception& e) {
+ MessageBox(g_hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
+ CleanD3D();
+ return EXIT_FAILURE;
+ } catch (...) {
+ MessageBox(g_hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
+ CleanD3D();
+ return EXIT_FAILURE;
+ }
+}
+
+void InitD3D(HINSTANCE /*hinstance*/, HWND hWnd)
+{
+ HRESULT hr;
+
+ UINT createDeviceFlags = 0;
+#ifdef _DEBUG
+ createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ D3D_DRIVER_TYPE driverTypes[] =
+ {
+ D3D_DRIVER_TYPE_HARDWARE,
+ D3D_DRIVER_TYPE_WARP,
+ D3D_DRIVER_TYPE_REFERENCE,
+ };
+ UINT numDriverTypes = ARRAYSIZE(driverTypes);
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ };
+ UINT numFeatureLevels = ARRAYSIZE(featureLevels);
+
+ for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
+ {
+ g_driverType = driverTypes[driverTypeIndex];
+ hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
+ D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
+
+ if (hr == E_INVALIDARG)
+ {
+ // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
+ hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
+ D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
+ }
+
+ if (SUCCEEDED(hr))
+ break;
+ }
+ if (FAILED(hr))
+ Throwanerror("Directx Device Creation Failed!");
+
+#if _DEBUG
+ hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug));
+ if (FAILED(hr))
+ OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n"));
+#endif
+
+ UINT m4xMsaaQuality;
+ dev->CheckMultisampleQualityLevels(
+ DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
+
+
+ // Obtain DXGI factory from device (since we used nullptr for pAdapter above)
+ IDXGIFactory1* dxgiFactory = nullptr;
+ {
+ IDXGIDevice* dxgiDevice = nullptr;
+ hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
+ if (SUCCEEDED(hr))
+ {
+ IDXGIAdapter* adapter = nullptr;
+ hr = dxgiDevice->GetAdapter(&adapter);
+ if (SUCCEEDED(hr))
+ {
+ hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
+ adapter->Release();
+ }
+ dxgiDevice->Release();
+ }
+ }
+ if (FAILED(hr))
+ Throwanerror("DXGI Factory couldn't be obtained!");
+
+ // Create swap chain
+ IDXGIFactory2* dxgiFactory2 = nullptr;
+ hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
+ if (dxgiFactory2)
+ {
+ // DirectX 11.1 or later
+ hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&dev1));
+ if (SUCCEEDED(hr))
+ {
+ (void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&devcon1));
+ }
+
+ DXGI_SWAP_CHAIN_DESC1 sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.Width = SCREEN_WIDTH;
+ sd.Height = SCREEN_HEIGHT;
+ sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.SampleDesc.Count = 4;
+ sd.SampleDesc.Quality = m4xMsaaQuality - 1;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.BufferCount = 1;
+
+ hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1);
+ if (SUCCEEDED(hr))
+ {
+ hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&swapchain));
+ }
+
+ dxgiFactory2->Release();
+ }
+ else
+ {
+ // DirectX 11.0 systems
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 1;
+ sd.BufferDesc.Width = SCREEN_WIDTH;
+ sd.BufferDesc.Height = SCREEN_HEIGHT;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = m4xMsaaQuality - 1;
+ sd.Windowed = TRUE;
+
+ hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain);
+ }
+
+ // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
+ dxgiFactory->MakeWindowAssociation(g_hwnd, DXGI_MWA_NO_ALT_ENTER);
+
+ dxgiFactory->Release();
+
+ if (FAILED(hr))
+ Throwanerror("Swapchain Creation Failed!");
+
+ ID3D11Texture2D *pBackBuffer;
+ swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
+
+ dev->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
+ pBackBuffer->Release();
+
+ D3D11_TEXTURE2D_DESC descDepth;
+ ZeroMemory(&descDepth, sizeof(descDepth));
+ descDepth.Width = SCREEN_WIDTH;
+ descDepth.Height = SCREEN_HEIGHT;
+ descDepth.MipLevels = 1;
+ descDepth.ArraySize = 1;
+ descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDepth.SampleDesc.Count = 4;
+ descDepth.SampleDesc.Quality = m4xMsaaQuality - 1;
+ descDepth.Usage = D3D11_USAGE_DEFAULT;
+ descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ descDepth.CPUAccessFlags = 0;
+ descDepth.MiscFlags = 0;
+ hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
+ if (FAILED(hr))
+ Throwanerror("Depth Stencil Texture couldn't be created!");
+
+ // Create the depth stencil view
+ D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
+ ZeroMemory(&descDSV, sizeof(descDSV));
+ descDSV.Format = descDepth.Format;
+ descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ descDSV.Texture2D.MipSlice = 0;
+ hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView);
+ if (FAILED(hr))
+ {
+ Throwanerror("Depth Stencil View couldn't be created!");
+ }
+
+ devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
+
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.AntialiasedLineEnable = false;
+ rasterDesc.CullMode = D3D11_CULL_BACK;
+ rasterDesc.DepthBias = 0;
+ rasterDesc.DepthBiasClamp = 0.0f;
+ rasterDesc.DepthClipEnable = true;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.FrontCounterClockwise = false;
+ rasterDesc.MultisampleEnable = false;
+ rasterDesc.ScissorEnable = false;
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+
+ dev->CreateRasterizerState(&rasterDesc, &rasterstate);
+ devcon->RSSetState(rasterstate);
+
+ D3D11_VIEWPORT viewport;
+ ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
+
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ viewport.Width = SCREEN_WIDTH;
+ viewport.Height = SCREEN_HEIGHT;
+
+ devcon->RSSetViewports(1, &viewport);
+
+ InitPipeline();
+ InitGraphics();
+}
+
+void CleanD3D(void)
+{
+ if (swapchain)
+ swapchain->SetFullscreenState(FALSE, nullptr);
+
+ if (ourModel) {
+ ourModel->Close();
+ delete ourModel;
+ ourModel = nullptr;
+ }
+ SafeRelease(TexSamplerState);
+ SafeRelease(pConstantBuffer);
+ SafeRelease(pLayout);
+ SafeRelease(pVS);
+ SafeRelease(pPS);
+ SafeRelease(rasterstate);
+ SafeRelease(g_pDepthStencilView);
+ SafeRelease(g_pDepthStencil);
+ SafeRelease(backbuffer);
+ SafeRelease(swapchain);
+ SafeRelease(swapchain1);
+ SafeRelease(devcon1);
+ SafeRelease(dev1);
+ SafeRelease(devcon);
+#if _DEBUG
+ if (d3d11debug) {
+ OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n"));
+ d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+ SafeRelease(d3d11debug);
+ } else {
+ OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n"));
+ }
+#endif
+ SafeRelease(dev);
+}
+
+void RenderFrame(void)
+{
+ static float t = 0.0f;
+ static ULONGLONG timeStart = 0;
+ ULONGLONG timeCur = GetTickCount64();
+ if (timeStart == 0)
+ timeStart = timeCur;
+ t = (timeCur - timeStart) / 1000.0f;
+
+ float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
+ devcon->ClearRenderTargetView(backbuffer, clearColor);
+ devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
+
+ devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ m_World = XMMatrixRotationY(-t);
+
+ ConstantBuffer cb;
+ cb.mWorld = XMMatrixTranspose(m_World);
+ cb.mView = XMMatrixTranspose(m_View);
+ cb.mProjection = XMMatrixTranspose(m_Projection);
+ devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0);
+
+ devcon->VSSetShader(pVS, 0, 0);
+ devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer);
+ devcon->PSSetShader(pPS, 0, 0);
+ devcon->PSSetSamplers(0, 1, &TexSamplerState);
+ ourModel->Draw(devcon);
+
+ swapchain->Present(0, 0);
+}
+
+void InitPipeline()
+{
+ ID3DBlob *VS, *PS;
+ if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS)))
+ Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str());
+ if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
+ Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
+
+ dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), nullptr, &pVS);
+ dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), nullptr, &pPS);
+
+ D3D11_INPUT_ELEMENT_DESC ied[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+ };
+
+ dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
+ devcon->IASetInputLayout(pLayout);
+}
+
+void InitGraphics()
+{
+ HRESULT hr;
+
+ m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f);
+
+ D3D11_BUFFER_DESC bd;
+ ZeroMemory(&bd, sizeof(bd));
+
+ bd.Usage = D3D11_USAGE_DEFAULT;
+ bd.ByteWidth = sizeof(ConstantBuffer);
+ bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bd.CPUAccessFlags = 0;
+
+ hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer);
+ if (FAILED(hr))
+ Throwanerror("Constant buffer couldn't be created");
+
+ D3D11_SAMPLER_DESC sampDesc;
+ ZeroMemory(&sampDesc, sizeof(sampDesc));
+ sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ sampDesc.MinLOD = 0;
+ sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
+
+ hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState);
+ if (FAILED(hr))
+ Throwanerror("Texture sampler state couldn't be created");
+
+ XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f);
+ XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f);
+ XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
+ m_View = XMMatrixLookAtLH(Eye, At, Up);
+
+ ourModel = new ModelLoader;
+ if (!ourModel->Load(g_hwnd, dev, devcon, g_ModelPath))
+ Throwanerror("Model couldn't be loaded");
+}
+
+HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob)
+{
+ UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
+
+#ifdef _DEBUG
+ compileFlags |= D3DCOMPILE_DEBUG;
+#endif
+
+ ID3DBlob* pErrorBlob = nullptr;
+
+ HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
+ if (FAILED(result))
+ {
+ if (pErrorBlob != nullptr)
+ OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
+ }
+
+ if (pErrorBlob != nullptr)
+ pErrorBlob->Release();
+
+ return result;
+}
+
+void Throwanerror(LPCSTR errormessage)
+{
+ throw std::runtime_error(errormessage);
+}