mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-13 17:30:51 +00:00
* Adjustment: Initial CMake reworking.
This commit is contained in:
parent
516163fd5d
commit
d7cdf54661
5394 changed files with 2615532 additions and 8711 deletions
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef MESH_H
|
||||
#define MESH_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <d3d11_1.h>
|
||||
#include <DirectXMath.h>
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
#include "SafeRelease.hpp"
|
||||
|
||||
struct VERTEX {
|
||||
FLOAT X, Y, Z;
|
||||
XMFLOAT2 texcoord;
|
||||
};
|
||||
|
||||
struct Texture {
|
||||
std::string type;
|
||||
std::string path;
|
||||
ID3D11ShaderResourceView *texture;
|
||||
|
||||
void Release() {
|
||||
SafeRelease(texture);
|
||||
}
|
||||
};
|
||||
|
||||
class Mesh {
|
||||
public:
|
||||
std::vector<VERTEX> vertices_;
|
||||
std::vector<UINT> indices_;
|
||||
std::vector<Texture> textures_;
|
||||
ID3D11Device *dev_;
|
||||
|
||||
Mesh(ID3D11Device *dev, const std::vector<VERTEX>& vertices, const std::vector<UINT>& indices, const std::vector<Texture>& textures) :
|
||||
vertices_(vertices),
|
||||
indices_(indices),
|
||||
textures_(textures),
|
||||
dev_(dev),
|
||||
VertexBuffer_(nullptr),
|
||||
IndexBuffer_(nullptr) {
|
||||
this->setupMesh(this->dev_);
|
||||
}
|
||||
|
||||
void Draw(ID3D11DeviceContext *devcon) {
|
||||
UINT stride = sizeof(VERTEX);
|
||||
UINT offset = 0;
|
||||
|
||||
devcon->IASetVertexBuffers(0, 1, &VertexBuffer_, &stride, &offset);
|
||||
devcon->IASetIndexBuffer(IndexBuffer_, DXGI_FORMAT_R32_UINT, 0);
|
||||
|
||||
devcon->PSSetShaderResources(0, 1, &textures_[0].texture);
|
||||
|
||||
devcon->DrawIndexed(static_cast<UINT>(indices_.size()), 0, 0);
|
||||
}
|
||||
|
||||
void Close() {
|
||||
SafeRelease(VertexBuffer_);
|
||||
SafeRelease(IndexBuffer_);
|
||||
}
|
||||
private:
|
||||
// Render data
|
||||
ID3D11Buffer *VertexBuffer_, *IndexBuffer_;
|
||||
|
||||
// Functions
|
||||
// Initializes all the buffer objects/arrays
|
||||
void setupMesh(ID3D11Device *dev) {
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_BUFFER_DESC vbd;
|
||||
vbd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices_.size());
|
||||
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vbd.CPUAccessFlags = 0;
|
||||
vbd.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &vertices_[0];
|
||||
|
||||
hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer_);
|
||||
if (FAILED(hr)) {
|
||||
Close();
|
||||
throw std::runtime_error("Failed to create vertex buffer.");
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC ibd;
|
||||
ibd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices_.size());
|
||||
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
ibd.CPUAccessFlags = 0;
|
||||
ibd.MiscFlags = 0;
|
||||
|
||||
initData.pSysMem = &indices_[0];
|
||||
|
||||
hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer_);
|
||||
if (FAILED(hr)) {
|
||||
Close();
|
||||
throw std::runtime_error("Failed to create index buffer.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
#include "ModelLoader.h"
|
||||
|
||||
ModelLoader::ModelLoader() :
|
||||
dev_(nullptr),
|
||||
devcon_(nullptr),
|
||||
meshes_(),
|
||||
directory_(),
|
||||
textures_loaded_(),
|
||||
hwnd_(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
ModelLoader::~ModelLoader() {
|
||||
// empty
|
||||
}
|
||||
|
||||
bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) {
|
||||
Assimp::Importer importer;
|
||||
|
||||
const aiScene* pScene = importer.ReadFile(filename,
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_ConvertToLeftHanded);
|
||||
|
||||
if (pScene == nullptr)
|
||||
return false;
|
||||
|
||||
this->directory_ = filename.substr(0, filename.find_last_of("/\\"));
|
||||
|
||||
this->dev_ = dev;
|
||||
this->devcon_ = devcon;
|
||||
this->hwnd_ = hwnd;
|
||||
|
||||
processNode(pScene->mRootNode, pScene);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
|
||||
for (size_t i = 0; i < meshes_.size(); ++i ) {
|
||||
meshes_[i].Draw(devcon);
|
||||
}
|
||||
}
|
||||
|
||||
Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
|
||||
// Data to fill
|
||||
std::vector<VERTEX> vertices;
|
||||
std::vector<UINT> indices;
|
||||
std::vector<Texture> textures;
|
||||
|
||||
// Walk through each of the mesh's vertices
|
||||
for (UINT i = 0; i < mesh->mNumVertices; i++) {
|
||||
VERTEX vertex;
|
||||
|
||||
vertex.X = mesh->mVertices[i].x;
|
||||
vertex.Y = mesh->mVertices[i].y;
|
||||
vertex.Z = mesh->mVertices[i].z;
|
||||
|
||||
if (mesh->mTextureCoords[0]) {
|
||||
vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
|
||||
vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
|
||||
}
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace face = mesh->mFaces[i];
|
||||
|
||||
for (UINT j = 0; j < face.mNumIndices; j++)
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
|
||||
if (mesh->mMaterialIndex >= 0) {
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
|
||||
std::vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
|
||||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||
}
|
||||
|
||||
return Mesh(dev_, vertices, indices, textures);
|
||||
}
|
||||
|
||||
std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
|
||||
std::vector<Texture> textures;
|
||||
for (UINT i = 0; i < mat->GetTextureCount(type); i++) {
|
||||
aiString str;
|
||||
mat->GetTexture(type, i, &str);
|
||||
// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
|
||||
bool skip = false;
|
||||
for (UINT j = 0; j < textures_loaded_.size(); j++) {
|
||||
if (std::strcmp(textures_loaded_[j].path.c_str(), str.C_Str()) == 0) {
|
||||
textures.push_back(textures_loaded_[j]);
|
||||
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!skip) { // If texture hasn't been loaded already, load it
|
||||
HRESULT hr;
|
||||
Texture texture;
|
||||
|
||||
const aiTexture* embeddedTexture = scene->GetEmbeddedTexture(str.C_Str());
|
||||
if (embeddedTexture != nullptr) {
|
||||
texture.texture = loadEmbeddedTexture(embeddedTexture);
|
||||
} else {
|
||||
std::string filename = std::string(str.C_Str());
|
||||
filename = directory_ + '/' + filename;
|
||||
std::wstring filenamews = std::wstring(filename.begin(), filename.end());
|
||||
hr = CreateWICTextureFromFile(dev_, devcon_, filenamews.c_str(), nullptr, &texture.texture);
|
||||
if (FAILED(hr))
|
||||
MessageBox(hwnd_, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
texture.type = typeName;
|
||||
texture.path = str.C_Str();
|
||||
textures.push_back(texture);
|
||||
this->textures_loaded_.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
|
||||
}
|
||||
}
|
||||
return textures;
|
||||
}
|
||||
|
||||
void ModelLoader::Close() {
|
||||
for (auto& t : textures_loaded_)
|
||||
t.Release();
|
||||
|
||||
for (size_t i = 0; i < meshes_.size(); i++) {
|
||||
meshes_[i].Close();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
|
||||
for (UINT i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes_.push_back(this->processMesh(mesh, scene));
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < node->mNumChildren; i++) {
|
||||
this->processNode(node->mChildren[i], scene);
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView * ModelLoader::loadEmbeddedTexture(const aiTexture* embeddedTexture) {
|
||||
HRESULT hr;
|
||||
ID3D11ShaderResourceView *texture = nullptr;
|
||||
|
||||
if (embeddedTexture->mHeight != 0) {
|
||||
// Load an uncompressed ARGB8888 embedded texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = embeddedTexture->mWidth;
|
||||
desc.Height = embeddedTexture->mHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA subresourceData;
|
||||
subresourceData.pSysMem = embeddedTexture->pcData;
|
||||
subresourceData.SysMemPitch = embeddedTexture->mWidth * 4;
|
||||
subresourceData.SysMemSlicePitch = embeddedTexture->mWidth * embeddedTexture->mHeight * 4;
|
||||
|
||||
ID3D11Texture2D *texture2D = nullptr;
|
||||
hr = dev_->CreateTexture2D(&desc, &subresourceData, &texture2D);
|
||||
if (FAILED(hr))
|
||||
MessageBox(hwnd_, "CreateTexture2D failed!", "Error!", MB_ICONERROR | MB_OK);
|
||||
|
||||
hr = dev_->CreateShaderResourceView(texture2D, nullptr, &texture);
|
||||
if (FAILED(hr))
|
||||
MessageBox(hwnd_, "CreateShaderResourceView failed!", "Error!", MB_ICONERROR | MB_OK);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
// mHeight is 0, so try to load a compressed texture of mWidth bytes
|
||||
const size_t size = embeddedTexture->mWidth;
|
||||
|
||||
hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<const unsigned char*>(embeddedTexture->pcData), size, nullptr, &texture);
|
||||
if (FAILED(hr))
|
||||
MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef MODEL_LOADER_H
|
||||
#define MODEL_LOADER_H
|
||||
|
||||
#include <vector>
|
||||
#include <d3d11_1.h>
|
||||
#include <DirectXMath.h>
|
||||
|
||||
#include <assimp\Importer.hpp>
|
||||
#include <assimp\scene.h>
|
||||
#include <assimp\postprocess.h>
|
||||
|
||||
#include "Mesh.h"
|
||||
#include "TextureLoader.h"
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
class ModelLoader
|
||||
{
|
||||
public:
|
||||
ModelLoader();
|
||||
~ModelLoader();
|
||||
|
||||
bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
|
||||
void Draw(ID3D11DeviceContext* devcon);
|
||||
|
||||
void Close();
|
||||
private:
|
||||
ID3D11Device *dev_;
|
||||
ID3D11DeviceContext *devcon_;
|
||||
std::vector<Mesh> meshes_;
|
||||
std::string directory_;
|
||||
std::vector<Texture> textures_loaded_;
|
||||
HWND hwnd_;
|
||||
|
||||
void processNode(aiNode* node, const aiScene* scene);
|
||||
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
|
||||
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene);
|
||||
ID3D11ShaderResourceView* loadEmbeddedTexture(const aiTexture* embeddedTexture);
|
||||
};
|
||||
|
||||
#endif // !MODEL_LOADER_H
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Used to reduce to reduce the number of lines when calling Release()
|
||||
on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE'
|
||||
MACRO to ease debugging. */
|
||||
template<typename T>
|
||||
inline void SafeRelease(T*& x) {
|
||||
if (x) {
|
||||
x->Release();
|
||||
x = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,697 @@
|
|||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// We could load multi-frame images (TIFF/GIF) into a texture array.
|
||||
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
|
||||
|
||||
#include <dxgiformat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <wincodec.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "TextureLoader.h"
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
|
||||
#define DXGI_1_2_FORMATS
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class T> class ScopedObject
|
||||
{
|
||||
public:
|
||||
explicit ScopedObject(T *p = 0) : _pointer(p) {}
|
||||
~ScopedObject()
|
||||
{
|
||||
if (_pointer)
|
||||
{
|
||||
_pointer->Release();
|
||||
_pointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNull() const { return (!_pointer); }
|
||||
|
||||
T& operator*() { return *_pointer; }
|
||||
T* operator->() { return _pointer; }
|
||||
T** operator&() { return &_pointer; }
|
||||
|
||||
void Reset(T *p = 0) { if (_pointer) { _pointer->Release(); } _pointer = p; }
|
||||
|
||||
T* Get() const { return _pointer; }
|
||||
|
||||
private:
|
||||
ScopedObject(const ScopedObject&);
|
||||
ScopedObject& operator=(const ScopedObject&);
|
||||
|
||||
T* _pointer;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format Translation Data
|
||||
//-------------------------------------------------------------------------------------
|
||||
struct WICTranslate
|
||||
{
|
||||
GUID wic;
|
||||
DXGI_FORMAT format;
|
||||
};
|
||||
|
||||
static WICTranslate g_WICFormats[] =
|
||||
{
|
||||
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
|
||||
|
||||
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
|
||||
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
|
||||
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
|
||||
{ GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
|
||||
|
||||
#ifdef DXGI_1_2_FORMATS
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
|
||||
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
|
||||
|
||||
#endif // DXGI_1_2_FORMATS
|
||||
|
||||
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
|
||||
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
|
||||
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
|
||||
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
|
||||
|
||||
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||
{ GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
|
||||
#endif
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format nearest conversion table
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
struct WICConvert
|
||||
{
|
||||
GUID source;
|
||||
GUID target;
|
||||
};
|
||||
|
||||
static WICConvert g_WICConvert[] =
|
||||
{
|
||||
// Note target GUID in this conversion table must be one of those directly supported formats (above).
|
||||
|
||||
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
|
||||
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
|
||||
|
||||
#ifdef DXGI_1_2_FORMATS
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
|
||||
|
||||
#else
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
|
||||
#endif // DXGI_1_2_FORMATS
|
||||
|
||||
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
|
||||
{ GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
|
||||
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||
#endif
|
||||
|
||||
// We don't support n-channel formats
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
static IWICImagingFactory* _GetWIC()
|
||||
{
|
||||
static IWICImagingFactory* s_Factory = nullptr;
|
||||
|
||||
if (s_Factory)
|
||||
return s_Factory;
|
||||
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
(LPVOID*)&s_Factory
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
s_Factory = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return s_Factory;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static DXGI_FORMAT _WICToDXGI(const GUID& guid)
|
||||
{
|
||||
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
|
||||
{
|
||||
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
|
||||
return g_WICFormats[i].format;
|
||||
}
|
||||
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static size_t _WICBitsPerPixel(REFGUID targetGuid)
|
||||
{
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return 0;
|
||||
|
||||
ScopedObject<IWICComponentInfo> cinfo;
|
||||
if (FAILED(pWIC->CreateComponentInfo(targetGuid, &cinfo)))
|
||||
return 0;
|
||||
|
||||
WICComponentType type;
|
||||
if (FAILED(cinfo->GetComponentType(&type)))
|
||||
return 0;
|
||||
|
||||
if (type != WICPixelFormat)
|
||||
return 0;
|
||||
|
||||
ScopedObject<IWICPixelFormatInfo> pfinfo;
|
||||
if (FAILED(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>(&pfinfo))))
|
||||
return 0;
|
||||
|
||||
UINT bpp;
|
||||
if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
|
||||
return 0;
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_ IWICBitmapFrameDecode *frame,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize)
|
||||
{
|
||||
UINT width, height;
|
||||
HRESULT hr = frame->GetSize(&width, &height);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
assert(width > 0 && height > 0);
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
// This is a bit conservative because the hardware could support larger textures than
|
||||
// the Feature Level defined minimums, but doing it this way is much easier and more
|
||||
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
|
||||
|
||||
switch (d3dDevice->GetFeatureLevel())
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
break;
|
||||
|
||||
default:
|
||||
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(maxsize > 0);
|
||||
|
||||
UINT twidth, theight;
|
||||
if (width > maxsize || height > maxsize)
|
||||
{
|
||||
float ar = static_cast<float>(height) / static_cast<float>(width);
|
||||
if (width > height)
|
||||
{
|
||||
twidth = static_cast<UINT>(maxsize);
|
||||
theight = static_cast<UINT>(static_cast<float>(maxsize) * ar);
|
||||
}
|
||||
else
|
||||
{
|
||||
theight = static_cast<UINT>(maxsize);
|
||||
twidth = static_cast<UINT>(static_cast<float>(maxsize) / ar);
|
||||
}
|
||||
assert(twidth <= maxsize && theight <= maxsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
twidth = width;
|
||||
theight = height;
|
||||
}
|
||||
|
||||
// Determine format
|
||||
WICPixelFormatGUID pixelFormat;
|
||||
hr = frame->GetPixelFormat(&pixelFormat);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID convertGUID;
|
||||
memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID));
|
||||
|
||||
size_t bpp = 0;
|
||||
|
||||
DXGI_FORMAT format = _WICToDXGI(pixelFormat);
|
||||
if (format == DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
for (size_t i = 0; i < _countof(g_WICConvert); ++i)
|
||||
{
|
||||
if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
|
||||
{
|
||||
memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID));
|
||||
|
||||
format = _WICToDXGI(g_WICConvert[i].target);
|
||||
assert(format != DXGI_FORMAT_UNKNOWN);
|
||||
bpp = _WICBitsPerPixel(convertGUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (format == DXGI_FORMAT_UNKNOWN)
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
bpp = _WICBitsPerPixel(pixelFormat);
|
||||
}
|
||||
|
||||
if (!bpp)
|
||||
return E_FAIL;
|
||||
|
||||
// Verify our target format is supported by the current device
|
||||
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
|
||||
UINT support = 0;
|
||||
hr = d3dDevice->CheckFormatSupport(format, &support);
|
||||
if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
|
||||
{
|
||||
// Fallback to RGBA 32-bit format which is supported by all devices
|
||||
memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID));
|
||||
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bpp = 32;
|
||||
}
|
||||
|
||||
// Allocate temporary memory for image
|
||||
size_t rowPitch = (twidth * bpp + 7) / 8;
|
||||
size_t imageSize = rowPitch * theight;
|
||||
|
||||
std::unique_ptr<uint8_t[]> temp(new uint8_t[imageSize]);
|
||||
|
||||
// Load image data
|
||||
if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
|
||||
&& twidth == width
|
||||
&& theight == height)
|
||||
{
|
||||
// No format conversion or resize needed
|
||||
hr = frame->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else if (twidth != width || theight != height)
|
||||
{
|
||||
// Resize
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ScopedObject<IWICBitmapScaler> scaler;
|
||||
hr = pWIC->CreateBitmapScaler(&scaler);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID pfScaler;
|
||||
hr = scaler->GetPixelFormat(&pfScaler);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
|
||||
{
|
||||
// No format conversion needed
|
||||
hr = scaler->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScopedObject<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(&FC);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Format conversion but no resize
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ScopedObject<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(&FC);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
// See if format is supported for auto-gen mipmaps (varies by feature level)
|
||||
bool autogen = false;
|
||||
if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
|
||||
{
|
||||
UINT fmtSupport = 0;
|
||||
hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
|
||||
if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
|
||||
{
|
||||
autogen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = twidth;
|
||||
desc.Height = theight;
|
||||
desc.MipLevels = (autogen) ? 0 : 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = temp.get();
|
||||
initData.SysMemPitch = static_cast<UINT>(rowPitch);
|
||||
initData.SysMemSlicePitch = static_cast<UINT>(imageSize);
|
||||
|
||||
ID3D11Texture2D* tex = nullptr;
|
||||
hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex);
|
||||
if (SUCCEEDED(hr) && tex != 0)
|
||||
{
|
||||
if (textureView != 0)
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
|
||||
memset(&SRVDesc, 0, sizeof(SRVDesc));
|
||||
SRVDesc.Format = format;
|
||||
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
|
||||
|
||||
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
tex->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (autogen)
|
||||
{
|
||||
assert(d3dContext != 0);
|
||||
d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize));
|
||||
d3dContext->GenerateMips(*textureView);
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != 0)
|
||||
{
|
||||
*texture = tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_DEBUG) || defined(PROFILE)
|
||||
tex->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader") - 1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
#endif
|
||||
tex->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize
|
||||
)
|
||||
{
|
||||
if (!d3dDevice || !wicData || (!texture && !textureView))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!wicDataSize)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
if (wicDataSize > 0xFFFFFFFF)
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
|
||||
#endif
|
||||
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Create input stream for memory
|
||||
ScopedObject<IWICStream> stream;
|
||||
HRESULT hr = pWIC->CreateStream(&stream);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Initialize WIC
|
||||
ScopedObject<IWICBitmapDecoder> decoder;
|
||||
hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ScopedObject<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, &frame);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
#if defined(_DEBUG) || defined(PROFILE)
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader") - 1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0)
|
||||
{
|
||||
(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader") - 1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize)
|
||||
{
|
||||
if (!d3dDevice || !fileName || (!texture && !textureView))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Initialize WIC
|
||||
ScopedObject<IWICBitmapDecoder> decoder;
|
||||
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ScopedObject<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, &frame);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
#if defined(_DEBUG) || defined(PROFILE)
|
||||
if (texture != 0 || textureView != 0)
|
||||
{
|
||||
CHAR strFileA[MAX_PATH];
|
||||
WideCharToMultiByte(CP_ACP,
|
||||
WC_NO_BEST_FIT_CHARS,
|
||||
fileName,
|
||||
-1,
|
||||
strFileA,
|
||||
MAX_PATH,
|
||||
nullptr,
|
||||
FALSE
|
||||
);
|
||||
const CHAR* pstrName = strrchr(strFileA, '\\');
|
||||
if (!pstrName)
|
||||
{
|
||||
pstrName = strFileA;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstrName++;
|
||||
}
|
||||
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0)
|
||||
{
|
||||
(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.h
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,599 @@
|
|||
// ---------------------------------------------------------------------------
|
||||
// Simple Assimp Directx11 Sample
|
||||
// This is a very basic sample and only reads diffuse texture
|
||||
// but this can load both embedded textures in fbx and non-embedded textures
|
||||
//
|
||||
//
|
||||
// Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your
|
||||
// model name (line 480)
|
||||
// If your model isn't a fbx with embedded textures make sure your model's
|
||||
// textures are in same directory as your model
|
||||
//
|
||||
//
|
||||
// Written by IAS. :)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <stdexcept>
|
||||
#include <windowsx.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include "ModelLoader.h"
|
||||
#include "UTFConverter.h"
|
||||
#include "SafeRelease.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3d11.lib")
|
||||
#pragma comment (lib, "Dxgi.lib")
|
||||
#pragma comment(lib,"d3dcompiler.lib")
|
||||
#pragma comment (lib, "dxguid.lib")
|
||||
#endif // _MSC_VER
|
||||
|
||||
using namespace DirectX;
|
||||
using namespace AssimpSamples::SharedCode;
|
||||
|
||||
#define VERTEX_SHADER_FILE L"VertexShader.hlsl"
|
||||
#define PIXEL_SHADER_FILE L"PixelShader.hlsl"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Structs
|
||||
// ------------------------------------------------------------
|
||||
struct ConstantBuffer {
|
||||
XMMATRIX mWorld;
|
||||
XMMATRIX mView;
|
||||
XMMATRIX mProjection;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Window Variables
|
||||
// ------------------------------------------------------------
|
||||
#define SCREEN_WIDTH 800
|
||||
#define SCREEN_HEIGHT 600
|
||||
|
||||
const char g_szClassName[] = "directxWindowClass";
|
||||
|
||||
static std::string g_ModelPath;
|
||||
|
||||
UINT width, height;
|
||||
HWND g_hwnd = nullptr;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// DirectX Variables
|
||||
// ------------------------------------------------------------
|
||||
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
|
||||
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
ID3D11Device *dev = nullptr;
|
||||
ID3D11Device1 *dev1 = nullptr;
|
||||
ID3D11DeviceContext *devcon = nullptr;
|
||||
ID3D11DeviceContext1 *devcon1 = nullptr;
|
||||
IDXGISwapChain *swapchain = nullptr;
|
||||
IDXGISwapChain1 *swapchain1 = nullptr;
|
||||
ID3D11RenderTargetView *backbuffer = nullptr;
|
||||
ID3D11VertexShader *pVS = nullptr;
|
||||
ID3D11PixelShader *pPS = nullptr;
|
||||
ID3D11InputLayout *pLayout = nullptr;
|
||||
ID3D11Buffer *pConstantBuffer = nullptr;
|
||||
ID3D11Texture2D *g_pDepthStencil = nullptr;
|
||||
ID3D11DepthStencilView *g_pDepthStencilView = nullptr;
|
||||
ID3D11SamplerState *TexSamplerState = nullptr;
|
||||
ID3D11RasterizerState *rasterstate = nullptr;
|
||||
ID3D11Debug* d3d11debug = nullptr;
|
||||
|
||||
XMMATRIX m_World;
|
||||
XMMATRIX m_View;
|
||||
XMMATRIX m_Projection;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Function identifiers
|
||||
// ------------------------------------------------------------
|
||||
|
||||
void InitD3D(HINSTANCE hinstance, HWND hWnd);
|
||||
void CleanD3D(void);
|
||||
void RenderFrame(void);
|
||||
|
||||
void InitPipeline();
|
||||
void InitGraphics();
|
||||
|
||||
HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob);
|
||||
void Throwanerror(LPCSTR errormessage);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Our Model
|
||||
// ------------------------------------------------------------
|
||||
|
||||
ModelLoader *ourModel = nullptr;
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(hwnd);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
|
||||
LPWSTR /*lpCmdLine*/, int nCmdShow)
|
||||
{
|
||||
int argc;
|
||||
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
if (!argv) {
|
||||
MessageBox(nullptr,
|
||||
TEXT("An error occurred while reading command line arguments."),
|
||||
TEXT("Error!"),
|
||||
MB_ICONERROR | MB_OK);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Free memory allocated from CommandLineToArgvW.
|
||||
auto free_command_line_allocated_memory = [&argv]() {
|
||||
if (argv) {
|
||||
LocalFree(argv);
|
||||
argv = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure that a model file has been specified.
|
||||
if (argc < 2) {
|
||||
MessageBox(nullptr,
|
||||
TEXT("No model file specified. The program will now close."),
|
||||
TEXT("Error!"),
|
||||
MB_ICONERROR | MB_OK);
|
||||
free_command_line_allocated_memory();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Retrieve the model file path.
|
||||
g_ModelPath = UTFConverter(argv[1]).str();
|
||||
|
||||
free_command_line_allocated_memory();
|
||||
|
||||
WNDCLASSEX wc;
|
||||
MSG msg;
|
||||
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hbrBackground = nullptr;
|
||||
wc.lpszMenuName = nullptr;
|
||||
wc.lpszClassName = g_szClassName;
|
||||
wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
|
||||
|
||||
if (!RegisterClassEx(&wc))
|
||||
{
|
||||
MessageBox(nullptr, "Window Registration Failed!", "Error!",
|
||||
MB_ICONEXCLAMATION | MB_OK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
|
||||
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
|
||||
g_hwnd = CreateWindowEx(
|
||||
WS_EX_CLIENTEDGE,
|
||||
g_szClassName,
|
||||
" Simple Textured Directx11 Sample ",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
|
||||
nullptr, nullptr, hInstance, nullptr
|
||||
);
|
||||
|
||||
if (g_hwnd == nullptr)
|
||||
{
|
||||
MessageBox(nullptr, "Window Creation Failed!", "Error!",
|
||||
MB_ICONEXCLAMATION | MB_OK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ShowWindow(g_hwnd, nCmdShow);
|
||||
UpdateWindow(g_hwnd);
|
||||
|
||||
width = wr.right - wr.left;
|
||||
height = wr.bottom - wr.top;
|
||||
|
||||
try {
|
||||
InitD3D(hInstance, g_hwnd);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
if (msg.message == WM_QUIT)
|
||||
break;
|
||||
}
|
||||
|
||||
RenderFrame();
|
||||
}
|
||||
|
||||
CleanD3D();
|
||||
return static_cast<int>(msg.wParam);
|
||||
} catch (const std::exception& e) {
|
||||
MessageBox(g_hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
|
||||
CleanD3D();
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
MessageBox(g_hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
|
||||
CleanD3D();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
void InitD3D(HINSTANCE /*hinstance*/, HWND hWnd)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
UINT createDeviceFlags = 0;
|
||||
#ifdef _DEBUG
|
||||
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
D3D_DRIVER_TYPE driverTypes[] =
|
||||
{
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
D3D_DRIVER_TYPE_WARP,
|
||||
D3D_DRIVER_TYPE_REFERENCE,
|
||||
};
|
||||
UINT numDriverTypes = ARRAYSIZE(driverTypes);
|
||||
|
||||
D3D_FEATURE_LEVEL featureLevels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
};
|
||||
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
|
||||
|
||||
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
|
||||
{
|
||||
g_driverType = driverTypes[driverTypeIndex];
|
||||
hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
|
||||
D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
|
||||
|
||||
if (hr == E_INVALIDARG)
|
||||
{
|
||||
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
|
||||
hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
|
||||
D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
break;
|
||||
}
|
||||
if (FAILED(hr))
|
||||
Throwanerror("Directx Device Creation Failed!");
|
||||
|
||||
#if _DEBUG
|
||||
hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug));
|
||||
if (FAILED(hr))
|
||||
OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n"));
|
||||
#endif
|
||||
|
||||
UINT m4xMsaaQuality;
|
||||
dev->CheckMultisampleQualityLevels(
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
|
||||
|
||||
|
||||
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
|
||||
IDXGIFactory1* dxgiFactory = nullptr;
|
||||
{
|
||||
IDXGIDevice* dxgiDevice = nullptr;
|
||||
hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IDXGIAdapter* adapter = nullptr;
|
||||
hr = dxgiDevice->GetAdapter(&adapter);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
|
||||
adapter->Release();
|
||||
}
|
||||
dxgiDevice->Release();
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
Throwanerror("DXGI Factory couldn't be obtained!");
|
||||
|
||||
// Create swap chain
|
||||
IDXGIFactory2* dxgiFactory2 = nullptr;
|
||||
hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
|
||||
if (dxgiFactory2)
|
||||
{
|
||||
// DirectX 11.1 or later
|
||||
hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&dev1));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&devcon1));
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.Width = SCREEN_WIDTH;
|
||||
sd.Height = SCREEN_HEIGHT;
|
||||
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.SampleDesc.Count = 4;
|
||||
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.BufferCount = 1;
|
||||
|
||||
hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&swapchain));
|
||||
}
|
||||
|
||||
dxgiFactory2->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// DirectX 11.0 systems
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.BufferCount = 1;
|
||||
sd.BufferDesc.Width = SCREEN_WIDTH;
|
||||
sd.BufferDesc.Height = SCREEN_HEIGHT;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.OutputWindow = hWnd;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||
sd.Windowed = TRUE;
|
||||
|
||||
hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain);
|
||||
}
|
||||
|
||||
// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
|
||||
dxgiFactory->MakeWindowAssociation(g_hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
|
||||
dxgiFactory->Release();
|
||||
|
||||
if (FAILED(hr))
|
||||
Throwanerror("Swapchain Creation Failed!");
|
||||
|
||||
ID3D11Texture2D *pBackBuffer;
|
||||
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
||||
|
||||
dev->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
|
||||
pBackBuffer->Release();
|
||||
|
||||
D3D11_TEXTURE2D_DESC descDepth;
|
||||
ZeroMemory(&descDepth, sizeof(descDepth));
|
||||
descDepth.Width = SCREEN_WIDTH;
|
||||
descDepth.Height = SCREEN_HEIGHT;
|
||||
descDepth.MipLevels = 1;
|
||||
descDepth.ArraySize = 1;
|
||||
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
descDepth.SampleDesc.Count = 4;
|
||||
descDepth.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||
descDepth.Usage = D3D11_USAGE_DEFAULT;
|
||||
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
descDepth.CPUAccessFlags = 0;
|
||||
descDepth.MiscFlags = 0;
|
||||
hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
|
||||
if (FAILED(hr))
|
||||
Throwanerror("Depth Stencil Texture couldn't be created!");
|
||||
|
||||
// Create the depth stencil view
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
|
||||
ZeroMemory(&descDSV, sizeof(descDSV));
|
||||
descDSV.Format = descDepth.Format;
|
||||
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
descDSV.Texture2D.MipSlice = 0;
|
||||
hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Throwanerror("Depth Stencil View couldn't be created!");
|
||||
}
|
||||
|
||||
devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
|
||||
|
||||
D3D11_RASTERIZER_DESC rasterDesc;
|
||||
rasterDesc.AntialiasedLineEnable = false;
|
||||
rasterDesc.CullMode = D3D11_CULL_BACK;
|
||||
rasterDesc.DepthBias = 0;
|
||||
rasterDesc.DepthBiasClamp = 0.0f;
|
||||
rasterDesc.DepthClipEnable = true;
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasterDesc.FrontCounterClockwise = false;
|
||||
rasterDesc.MultisampleEnable = false;
|
||||
rasterDesc.ScissorEnable = false;
|
||||
rasterDesc.SlopeScaledDepthBias = 0.0f;
|
||||
|
||||
dev->CreateRasterizerState(&rasterDesc, &rasterstate);
|
||||
devcon->RSSetState(rasterstate);
|
||||
|
||||
D3D11_VIEWPORT viewport;
|
||||
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
|
||||
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.Width = SCREEN_WIDTH;
|
||||
viewport.Height = SCREEN_HEIGHT;
|
||||
|
||||
devcon->RSSetViewports(1, &viewport);
|
||||
|
||||
InitPipeline();
|
||||
InitGraphics();
|
||||
}
|
||||
|
||||
void CleanD3D(void)
|
||||
{
|
||||
if (swapchain)
|
||||
swapchain->SetFullscreenState(FALSE, nullptr);
|
||||
|
||||
if (ourModel) {
|
||||
ourModel->Close();
|
||||
delete ourModel;
|
||||
ourModel = nullptr;
|
||||
}
|
||||
SafeRelease(TexSamplerState);
|
||||
SafeRelease(pConstantBuffer);
|
||||
SafeRelease(pLayout);
|
||||
SafeRelease(pVS);
|
||||
SafeRelease(pPS);
|
||||
SafeRelease(rasterstate);
|
||||
SafeRelease(g_pDepthStencilView);
|
||||
SafeRelease(g_pDepthStencil);
|
||||
SafeRelease(backbuffer);
|
||||
SafeRelease(swapchain);
|
||||
SafeRelease(swapchain1);
|
||||
SafeRelease(devcon1);
|
||||
SafeRelease(dev1);
|
||||
SafeRelease(devcon);
|
||||
#if _DEBUG
|
||||
if (d3d11debug) {
|
||||
OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n"));
|
||||
d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
|
||||
SafeRelease(d3d11debug);
|
||||
} else {
|
||||
OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n"));
|
||||
}
|
||||
#endif
|
||||
SafeRelease(dev);
|
||||
}
|
||||
|
||||
void RenderFrame(void)
|
||||
{
|
||||
static float t = 0.0f;
|
||||
static ULONGLONG timeStart = 0;
|
||||
ULONGLONG timeCur = GetTickCount64();
|
||||
if (timeStart == 0)
|
||||
timeStart = timeCur;
|
||||
t = (timeCur - timeStart) / 1000.0f;
|
||||
|
||||
float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
|
||||
devcon->ClearRenderTargetView(backbuffer, clearColor);
|
||||
devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
|
||||
|
||||
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
m_World = XMMatrixRotationY(-t);
|
||||
|
||||
ConstantBuffer cb;
|
||||
cb.mWorld = XMMatrixTranspose(m_World);
|
||||
cb.mView = XMMatrixTranspose(m_View);
|
||||
cb.mProjection = XMMatrixTranspose(m_Projection);
|
||||
devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0);
|
||||
|
||||
devcon->VSSetShader(pVS, 0, 0);
|
||||
devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer);
|
||||
devcon->PSSetShader(pPS, 0, 0);
|
||||
devcon->PSSetSamplers(0, 1, &TexSamplerState);
|
||||
ourModel->Draw(devcon);
|
||||
|
||||
swapchain->Present(0, 0);
|
||||
}
|
||||
|
||||
void InitPipeline()
|
||||
{
|
||||
ID3DBlob *VS, *PS;
|
||||
if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS)))
|
||||
Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str());
|
||||
if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
|
||||
Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
|
||||
|
||||
dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), nullptr, &pVS);
|
||||
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), nullptr, &pPS);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC ied[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
};
|
||||
|
||||
dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
|
||||
devcon->IASetInputLayout(pLayout);
|
||||
}
|
||||
|
||||
void InitGraphics()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f);
|
||||
|
||||
D3D11_BUFFER_DESC bd;
|
||||
ZeroMemory(&bd, sizeof(bd));
|
||||
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.ByteWidth = sizeof(ConstantBuffer);
|
||||
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
bd.CPUAccessFlags = 0;
|
||||
|
||||
hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer);
|
||||
if (FAILED(hr))
|
||||
Throwanerror("Constant buffer couldn't be created");
|
||||
|
||||
D3D11_SAMPLER_DESC sampDesc;
|
||||
ZeroMemory(&sampDesc, sizeof(sampDesc));
|
||||
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
sampDesc.MinLOD = 0;
|
||||
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
|
||||
hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState);
|
||||
if (FAILED(hr))
|
||||
Throwanerror("Texture sampler state couldn't be created");
|
||||
|
||||
XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f);
|
||||
XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f);
|
||||
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
|
||||
m_View = XMMatrixLookAtLH(Eye, At, Up);
|
||||
|
||||
ourModel = new ModelLoader;
|
||||
if (!ourModel->Load(g_hwnd, dev, devcon, g_ModelPath))
|
||||
Throwanerror("Model couldn't be loaded");
|
||||
}
|
||||
|
||||
HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob)
|
||||
{
|
||||
UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
|
||||
|
||||
#ifdef _DEBUG
|
||||
compileFlags |= D3DCOMPILE_DEBUG;
|
||||
#endif
|
||||
|
||||
ID3DBlob* pErrorBlob = nullptr;
|
||||
|
||||
HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
|
||||
if (FAILED(result))
|
||||
{
|
||||
if (pErrorBlob != nullptr)
|
||||
OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
|
||||
}
|
||||
|
||||
if (pErrorBlob != nullptr)
|
||||
pErrorBlob->Release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Throwanerror(LPCSTR errormessage)
|
||||
{
|
||||
throw std::runtime_error(errormessage);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue