Explorar el Código

Sample: update dx11 texture loader.

Kim Kulling hace 8 años
padre
commit
ff83701a6f

+ 102 - 102
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -1,102 +1,102 @@
-#ifndef MESH_H
-#define MESH_H
-
-#include <string>
-#include <fstream>
-#include <sstream>
-#include <iostream>
-#include <vector>
-using namespace std;
-
-#include <vector>
-#include <d3d11_1.h>
-#include <DirectXMath.h>
-using namespace DirectX;
-
-struct VERTEX {
-	FLOAT X, Y, Z;
-	XMFLOAT2 texcoord;
-};
-
-struct Texture {
-	string type;
-	string path;
-	ID3D11ShaderResourceView *texture;
-};
-
-class Mesh {
-public:
-	vector<VERTEX> vertices;
-	vector<UINT> indices;
-	vector<Texture> textures;
-	ID3D11Device *dev;
-
-	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
-	{
-		this->vertices = vertices;
-		this->indices = indices;
-		this->textures = textures;
-
-		this->dev = dev;
-
-		this->setupMesh(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(indices.size(), 0, 0);
-	}
-
-	void Close()
-	{
-		VertexBuffer->Release();
-		IndexBuffer->Release();
-	}
-private:
-	/*  Render data  */
-	ID3D11Buffer *VertexBuffer, *IndexBuffer;
-
-	/*  Functions    */
-	// Initializes all the buffer objects/arrays
-	bool setupMesh(ID3D11Device *dev)
-	{
-		HRESULT hr;
-
-		D3D11_BUFFER_DESC vbd;
-		vbd.Usage = D3D11_USAGE_IMMUTABLE;
-		vbd.ByteWidth = 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))
-			return false;
-
-		D3D11_BUFFER_DESC ibd;
-		ibd.Usage = D3D11_USAGE_IMMUTABLE;
-		ibd.ByteWidth = 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))
-			return false;
-	}
-};
-
-#endif
+#ifndef MESH_H
+#define MESH_H
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <vector>
+using namespace std;
+
+#include <vector>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+using namespace DirectX;
+
+struct VERTEX {
+	FLOAT X, Y, Z;
+	XMFLOAT2 texcoord;
+};
+
+struct Texture {
+	string type;
+	string path;
+	ID3D11ShaderResourceView *texture;
+};
+
+class Mesh {
+public:
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+	ID3D11Device *dev;
+
+	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
+	{
+		this->vertices = vertices;
+		this->indices = indices;
+		this->textures = textures;
+
+		this->dev = dev;
+
+		this->setupMesh(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(indices.size(), 0, 0);
+	}
+
+	void Close()
+	{
+		VertexBuffer->Release();
+		IndexBuffer->Release();
+	}
+private:
+	/*  Render data  */
+	ID3D11Buffer *VertexBuffer, *IndexBuffer;
+
+	/*  Functions    */
+	// Initializes all the buffer objects/arrays
+	bool setupMesh(ID3D11Device *dev)
+	{
+		HRESULT hr;
+
+		D3D11_BUFFER_DESC vbd;
+		vbd.Usage = D3D11_USAGE_IMMUTABLE;
+		vbd.ByteWidth = 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))
+			return false;
+
+		D3D11_BUFFER_DESC ibd;
+		ibd.Usage = D3D11_USAGE_IMMUTABLE;
+		ibd.ByteWidth = 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))
+			return false;
+	}
+};
+
+#endif

+ 205 - 205
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -1,205 +1,205 @@
-#include "ModelLoader.h"
-
-ModelLoader::ModelLoader()
-{
-}
-
-
-ModelLoader::~ModelLoader()
-{
-}
-
-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 == NULL)
-		return false;
-
-	this->directory = filename.substr(0, filename.find_last_of('/'));
-
-	this->dev = dev;
-	this->hwnd = hwnd;
-
-	processNode(pScene->mRootNode, pScene);
-
-	return true;
-}
-
-void ModelLoader::Draw(ID3D11DeviceContext * devcon)
-{
-	for (int i = 0; i < meshes.size(); i++)
-	{
-		meshes[i].Draw(devcon);
-	}
-}
-
-string textype;
-
-Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
-{
-	// Data to fill
-	vector<VERTEX> vertices;
-	vector<UINT> indices;
-	vector<Texture> textures;
-
-	if (mesh->mMaterialIndex >= 0)
-	{
-		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
-
-		if (textype.empty()) textype = determineTextureType(scene, mat);
-	}
-
-	// 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];
-
-		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);
-}
-
-vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
-{
-	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;
-			if (textype == "embedded compressed texture")
-			{
-				int textureindex = getTextureIndex(&str);
-				texture.texture = getTextureFromModel(scene, textureindex);
-			}
-			else
-			{
-				string filename = string(str.C_Str());
-				filename = directory + '/' + filename;
-				wstring filenamews = 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 (int i = 0; i < meshes.size(); i++)
-	{
-		meshes[i].Close();
-	}
-
-	dev->Release();
-}
-
-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);
-	}
-}
-
-string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
-{
-	aiString textypeStr;
-	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
-	string textypeteststr = textypeStr.C_Str();
-	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
-	{
-		if (scene->mTextures[0]->mHeight == 0)
-		{
-			return "embedded compressed texture";
-		}
-		else
-		{
-			return "embedded non-compressed texture";
-		}
-	}
-	if (textypeteststr.find('.') != string::npos)
-	{
-		return "textures are on disk";
-	}
-}
-
-int ModelLoader::getTextureIndex(aiString * str)
-{
-	string tistr;
-	tistr = str->C_Str();
-	tistr = tistr.substr(1);
-	return stoi(tistr);
-}
-
-ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
-{
-	HRESULT hr;
-	ID3D11ShaderResourceView *texture;
-
-	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
-
-	hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
-	if (FAILED(hr))
-		MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
-
-	return texture;
-}
+#include "ModelLoader.h"
+
+ModelLoader::ModelLoader()
+{
+}
+
+
+ModelLoader::~ModelLoader()
+{
+}
+
+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 == NULL)
+		return false;
+
+	this->directory = filename.substr(0, filename.find_last_of('/'));
+
+	this->dev = dev;
+	this->hwnd = hwnd;
+
+	processNode(pScene->mRootNode, pScene);
+
+	return true;
+}
+
+void ModelLoader::Draw(ID3D11DeviceContext * devcon)
+{
+	for (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Draw(devcon);
+	}
+}
+
+string textype;
+
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
+{
+	// Data to fill
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+
+	if (mesh->mMaterialIndex >= 0)
+	{
+		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
+
+		if (textype.empty()) textype = determineTextureType(scene, mat);
+	}
+
+	// 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];
+
+		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);
+}
+
+vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
+{
+	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;
+			if (textype == "embedded compressed texture")
+			{
+				int textureindex = getTextureIndex(&str);
+				texture.texture = getTextureFromModel(scene, textureindex);
+			}
+			else
+			{
+				string filename = string(str.C_Str());
+				filename = directory + '/' + filename;
+				wstring filenamews = 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 (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Close();
+	}
+
+	dev->Release();
+}
+
+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);
+	}
+}
+
+string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
+{
+	aiString textypeStr;
+	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
+	string textypeteststr = textypeStr.C_Str();
+	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
+	{
+		if (scene->mTextures[0]->mHeight == 0)
+		{
+			return "embedded compressed texture";
+		}
+		else
+		{
+			return "embedded non-compressed texture";
+		}
+	}
+	if (textypeteststr.find('.') != string::npos)
+	{
+		return "textures are on disk";
+	}
+}
+
+int ModelLoader::getTextureIndex(aiString * str)
+{
+	string tistr;
+	tistr = str->C_Str();
+	tistr = tistr.substr(1);
+	return stoi(tistr);
+}
+
+ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
+{
+	HRESULT hr;
+	ID3D11ShaderResourceView *texture;
+
+	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
+
+	hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
+	if (FAILED(hr))
+		MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+
+	return texture;
+}

+ 44 - 44
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h

@@ -1,44 +1,44 @@
-#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;
-	string directory;
-	vector<Texture> textures_loaded;
-	HWND hwnd;
-
-	void processNode(aiNode* node, const aiScene* scene);
-	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
-	vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
-	string determineTextureType(const aiScene* scene, aiMaterial* mat);
-	int getTextureIndex(aiString* str);
-	ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
-};
-
-#endif // !MODEL_LOADER_H
-
+#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;
+	string directory;
+	vector<Texture> textures_loaded;
+	HWND hwnd;
+
+	void processNode(aiNode* node, const aiScene* scene);
+	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
+	vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
+	string determineTextureType(const aiScene* scene, aiMaterial* mat);
+	int getTextureIndex(aiString* str);
+	ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
+};
+
+#endif // !MODEL_LOADER_H
+

+ 691 - 691
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp

@@ -1,691 +1,691 @@
-//--------------------------------------------------------------------------------------
-// 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>
-
-#pragma warning(push)
-#pragma warning(disable : 4005)
-#include <wincodec.h>
-#pragma warning(pop)
-
-#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;
-}
+//--------------------------------------------------------------------------------------
+// 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>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <wincodec.h>
+#pragma warning(pop)
+
+#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;
+}

+ 55 - 55
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h

@@ -1,55 +1,55 @@
-//--------------------------------------------------------------------------------------
-// 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>
-
-#pragma warning(push)
-#pragma warning(disable : 4005)
-#include <stdint.h>
-#pragma warning(pop)
-
-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
-);
-
+//--------------------------------------------------------------------------------------
+// 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>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <stdint.h>
+#pragma warning(pop)
+
+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
+);
+

+ 517 - 517
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -1,518 +1,518 @@
-// ---------------------------------------------------------------------------
-// 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 <windowsx.h>
-#include <d3d11_1.h>
-#include <dxgi1_2.h>
-#include <DirectXMath.h>
-#include <d3dcompiler.h>
-#include "ModelLoader.h"
-
-#pragma comment (lib, "d3d11.lib")
-#pragma comment (lib, "Dxgi.lib")
-#pragma comment(lib,"d3dcompiler.lib")
-#pragma comment (lib, "dxguid.lib")
-
-using namespace DirectX;
-
-// ------------------------------------------------------------
-//                        Structs
-// ------------------------------------------------------------
-struct ConstantBuffer {
-	XMMATRIX mWorld;
-	XMMATRIX mView;
-	XMMATRIX mProjection;
-};
-
-// ------------------------------------------------------------
-//                        Window Variables
-// ------------------------------------------------------------
-#define SCREEN_WIDTH  800
-#define SCREEN_HEIGHT 600
-
-const char g_szClassName[] = "directxWindowClass";
-
-
-UINT width, height;
-HWND hwnd;
-
-// ------------------------------------------------------------
-//                        DirectX Variables
-// ------------------------------------------------------------
-D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
-D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
-ID3D11Device *dev;
-ID3D11Device1 *dev1;
-ID3D11DeviceContext *devcon;
-ID3D11DeviceContext1 *devcon1;
-IDXGISwapChain *swapchain;
-IDXGISwapChain1 *swapchain1;
-ID3D11RenderTargetView *backbuffer;
-ID3D11VertexShader *pVS;
-ID3D11PixelShader *pPS;
-ID3D11InputLayout *pLayout;
-ID3D11Buffer *pConstantBuffer;
-ID3D11Texture2D *g_pDepthStencil;
-ID3D11DepthStencilView *g_pDepthStencilView;
-ID3D11SamplerState *TexSamplerState;
-
-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;
-
-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 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-	LPSTR lpCmdLine, int nCmdShow)
-{
-	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(NULL, IDI_APPLICATION);
-	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-	wc.hbrBackground = NULL;
-	wc.lpszMenuName = NULL;
-	wc.lpszClassName = g_szClassName;
-	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
-
-	if (!RegisterClassEx(&wc))
-	{
-		MessageBox(NULL, "Window Registration Failed!", "Error!",
-			MB_ICONEXCLAMATION | MB_OK);
-		return 0;
-	}
-
-	RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
-	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
-
-	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,
-		NULL, NULL, hInstance, NULL
-	);
-
-	if (hwnd == NULL)
-	{
-		MessageBox(NULL, "Window Creation Failed!", "Error!",
-			MB_ICONEXCLAMATION | MB_OK);
-		return 0;
-	}
-
-	ShowWindow(hwnd, nCmdShow);
-	UpdateWindow(hwnd);
-
-	width = wr.right - wr.left;
-	height = wr.bottom - wr.top;
-
-	InitD3D(hInstance, hwnd);
-
-	while (true)
-	{
-
-		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
-		{
-			TranslateMessage(&msg);
-			DispatchMessage(&msg);
-
-			if (msg.message == WM_QUIT)
-				break;
-		}
-
-		RenderFrame();
-	}
-
-	CleanD3D();
-
-	return msg.wParam;
-}
-
-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!");
-
-	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(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, NULL, &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;
-	ID3D11RasterizerState *rasterState;
-	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)
-{
-	swapchain->SetFullscreenState(FALSE, NULL);
-
-	ourModel->Close();
-	g_pDepthStencil->Release();
-	g_pDepthStencilView->Release();
-	pLayout->Release();
-	pVS->Release();
-	pPS->Release();
-	pConstantBuffer->Release();
-	swapchain->Release();
-	backbuffer->Release();
-	dev->Release();
-	devcon->Release();
-}
-
-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;
-	CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
-	CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
-
-	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
-	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &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(hwnd, dev, devcon, "Models/myModel.fbx"))
-		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 = NULL;
-
-	HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
-	if (FAILED(result))
-	{
-		if (pErrorBlob != NULL)
-			OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
-	}
-
-	if (pErrorBlob != NULL)
-		pErrorBlob->Release();
-
-	return result;
-}
-
-void Throwanerror(LPCSTR errormessage)
-{
-	MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
+// ---------------------------------------------------------------------------
+// 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 <windowsx.h>
+#include <d3d11_1.h>
+#include <dxgi1_2.h>
+#include <DirectXMath.h>
+#include <d3dcompiler.h>
+#include "ModelLoader.h"
+
+#pragma comment (lib, "d3d11.lib")
+#pragma comment (lib, "Dxgi.lib")
+#pragma comment(lib,"d3dcompiler.lib")
+#pragma comment (lib, "dxguid.lib")
+
+using namespace DirectX;
+
+// ------------------------------------------------------------
+//                        Structs
+// ------------------------------------------------------------
+struct ConstantBuffer {
+	XMMATRIX mWorld;
+	XMMATRIX mView;
+	XMMATRIX mProjection;
+};
+
+// ------------------------------------------------------------
+//                        Window Variables
+// ------------------------------------------------------------
+#define SCREEN_WIDTH  800
+#define SCREEN_HEIGHT 600
+
+const char g_szClassName[] = "directxWindowClass";
+
+
+UINT width, height;
+HWND hwnd;
+
+// ------------------------------------------------------------
+//                        DirectX Variables
+// ------------------------------------------------------------
+D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
+D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
+ID3D11Device *dev;
+ID3D11Device1 *dev1;
+ID3D11DeviceContext *devcon;
+ID3D11DeviceContext1 *devcon1;
+IDXGISwapChain *swapchain;
+IDXGISwapChain1 *swapchain1;
+ID3D11RenderTargetView *backbuffer;
+ID3D11VertexShader *pVS;
+ID3D11PixelShader *pPS;
+ID3D11InputLayout *pLayout;
+ID3D11Buffer *pConstantBuffer;
+ID3D11Texture2D *g_pDepthStencil;
+ID3D11DepthStencilView *g_pDepthStencilView;
+ID3D11SamplerState *TexSamplerState;
+
+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;
+
+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 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+	LPSTR lpCmdLine, int nCmdShow)
+{
+	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(NULL, IDI_APPLICATION);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = NULL;
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = g_szClassName;
+	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+	if (!RegisterClassEx(&wc))
+	{
+		MessageBox(NULL, "Window Registration Failed!", "Error!",
+			MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+
+	RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
+	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+
+	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,
+		NULL, NULL, hInstance, NULL
+	);
+
+	if (hwnd == NULL)
+	{
+		MessageBox(NULL, "Window Creation Failed!", "Error!",
+			MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+
+	ShowWindow(hwnd, nCmdShow);
+	UpdateWindow(hwnd);
+
+	width = wr.right - wr.left;
+	height = wr.bottom - wr.top;
+
+	InitD3D(hInstance, hwnd);
+
+	while (true)
+	{
+
+		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+		{
+			TranslateMessage(&msg);
+			DispatchMessage(&msg);
+
+			if (msg.message == WM_QUIT)
+				break;
+		}
+
+		RenderFrame();
+	}
+
+	CleanD3D();
+
+	return msg.wParam;
+}
+
+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!");
+
+	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(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, NULL, &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;
+	ID3D11RasterizerState *rasterState;
+	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)
+{
+	swapchain->SetFullscreenState(FALSE, NULL);
+
+	ourModel->Close();
+	g_pDepthStencil->Release();
+	g_pDepthStencilView->Release();
+	pLayout->Release();
+	pVS->Release();
+	pPS->Release();
+	pConstantBuffer->Release();
+	swapchain->Release();
+	backbuffer->Release();
+	dev->Release();
+	devcon->Release();
+}
+
+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;
+	CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
+	CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
+
+	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
+	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &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(hwnd, dev, devcon, "Models/myModel.fbx"))
+		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 = NULL;
+
+	HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
+	if (FAILED(result))
+	{
+		if (pErrorBlob != NULL)
+			OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
+	}
+
+	if (pErrorBlob != NULL)
+		pErrorBlob->Release();
+
+	return result;
+}
+
+void Throwanerror(LPCSTR errormessage)
+{
+	MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
 }