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