Sample: update dx11 texture loader.

pull/1261/merge
Kim Kulling 2017-06-03 09:25:20 +02:00
parent dcc5887817
commit ff83701a6f
6 changed files with 1614 additions and 1614 deletions

View File

@ -1,102 +1,102 @@
#ifndef MESH_H #ifndef MESH_H
#define MESH_H #define MESH_H
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
using namespace std; using namespace std;
#include <vector> #include <vector>
#include <d3d11_1.h> #include <d3d11_1.h>
#include <DirectXMath.h> #include <DirectXMath.h>
using namespace DirectX; using namespace DirectX;
struct VERTEX { struct VERTEX {
FLOAT X, Y, Z; FLOAT X, Y, Z;
XMFLOAT2 texcoord; XMFLOAT2 texcoord;
}; };
struct Texture { struct Texture {
string type; string type;
string path; string path;
ID3D11ShaderResourceView *texture; ID3D11ShaderResourceView *texture;
}; };
class Mesh { class Mesh {
public: public:
vector<VERTEX> vertices; vector<VERTEX> vertices;
vector<UINT> indices; vector<UINT> indices;
vector<Texture> textures; vector<Texture> textures;
ID3D11Device *dev; ID3D11Device *dev;
Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures) Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
{ {
this->vertices = vertices; this->vertices = vertices;
this->indices = indices; this->indices = indices;
this->textures = textures; this->textures = textures;
this->dev = dev; this->dev = dev;
this->setupMesh(dev); this->setupMesh(dev);
} }
void Draw(ID3D11DeviceContext *devcon) void Draw(ID3D11DeviceContext *devcon)
{ {
UINT stride = sizeof(VERTEX); UINT stride = sizeof(VERTEX);
UINT offset = 0; UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
devcon->PSSetShaderResources(0, 1, &textures[0].texture); devcon->PSSetShaderResources(0, 1, &textures[0].texture);
devcon->DrawIndexed(indices.size(), 0, 0); devcon->DrawIndexed(indices.size(), 0, 0);
} }
void Close() void Close()
{ {
VertexBuffer->Release(); VertexBuffer->Release();
IndexBuffer->Release(); IndexBuffer->Release();
} }
private: private:
/* Render data */ /* Render data */
ID3D11Buffer *VertexBuffer, *IndexBuffer; ID3D11Buffer *VertexBuffer, *IndexBuffer;
/* Functions */ /* Functions */
// Initializes all the buffer objects/arrays // Initializes all the buffer objects/arrays
bool setupMesh(ID3D11Device *dev) bool setupMesh(ID3D11Device *dev)
{ {
HRESULT hr; HRESULT hr;
D3D11_BUFFER_DESC vbd; D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE; vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(VERTEX) * vertices.size(); vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0; vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0; vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA initData; D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = &vertices[0]; initData.pSysMem = &vertices[0];
hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
if (FAILED(hr)) if (FAILED(hr))
return false; return false;
D3D11_BUFFER_DESC ibd; D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE; ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * indices.size(); ibd.ByteWidth = sizeof(UINT) * indices.size();
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0; ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0; ibd.MiscFlags = 0;
initData.pSysMem = &indices[0]; initData.pSysMem = &indices[0];
hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
if (FAILED(hr)) if (FAILED(hr))
return false; return false;
} }
}; };
#endif #endif

View File

@ -1,205 +1,205 @@
#include "ModelLoader.h" #include "ModelLoader.h"
ModelLoader::ModelLoader() ModelLoader::ModelLoader()
{ {
} }
ModelLoader::~ModelLoader() ModelLoader::~ModelLoader()
{ {
} }
bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename)
{ {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* pScene = importer.ReadFile(filename, const aiScene* pScene = importer.ReadFile(filename,
aiProcess_Triangulate | aiProcess_Triangulate |
aiProcess_ConvertToLeftHanded); aiProcess_ConvertToLeftHanded);
if (pScene == NULL) if (pScene == NULL)
return false; return false;
this->directory = filename.substr(0, filename.find_last_of('/')); this->directory = filename.substr(0, filename.find_last_of('/'));
this->dev = dev; this->dev = dev;
this->hwnd = hwnd; this->hwnd = hwnd;
processNode(pScene->mRootNode, pScene); processNode(pScene->mRootNode, pScene);
return true; return true;
} }
void ModelLoader::Draw(ID3D11DeviceContext * devcon) void ModelLoader::Draw(ID3D11DeviceContext * devcon)
{ {
for (int i = 0; i < meshes.size(); i++) for (int i = 0; i < meshes.size(); i++)
{ {
meshes[i].Draw(devcon); meshes[i].Draw(devcon);
} }
} }
string textype; string textype;
Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
{ {
// Data to fill // Data to fill
vector<VERTEX> vertices; vector<VERTEX> vertices;
vector<UINT> indices; vector<UINT> indices;
vector<Texture> textures; vector<Texture> textures;
if (mesh->mMaterialIndex >= 0) if (mesh->mMaterialIndex >= 0)
{ {
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
if (textype.empty()) textype = determineTextureType(scene, mat); if (textype.empty()) textype = determineTextureType(scene, mat);
} }
// Walk through each of the mesh's vertices // Walk through each of the mesh's vertices
for (UINT i = 0; i < mesh->mNumVertices; i++) for (UINT i = 0; i < mesh->mNumVertices; i++)
{ {
VERTEX vertex; VERTEX vertex;
vertex.X = mesh->mVertices[i].x; vertex.X = mesh->mVertices[i].x;
vertex.Y = mesh->mVertices[i].y; vertex.Y = mesh->mVertices[i].y;
vertex.Z = mesh->mVertices[i].z; vertex.Z = mesh->mVertices[i].z;
if (mesh->mTextureCoords[0]) if (mesh->mTextureCoords[0])
{ {
vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x; vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y; vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
} }
vertices.push_back(vertex); vertices.push_back(vertex);
} }
for (UINT i = 0; i < mesh->mNumFaces; i++) for (UINT i = 0; i < mesh->mNumFaces; i++)
{ {
aiFace face = mesh->mFaces[i]; aiFace face = mesh->mFaces[i];
for (UINT j = 0; j < face.mNumIndices; j++) for (UINT j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]); indices.push_back(face.mIndices[j]);
} }
if (mesh->mMaterialIndex >= 0) if (mesh->mMaterialIndex >= 0)
{ {
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
} }
return Mesh(dev, vertices, indices, textures); return Mesh(dev, vertices, indices, textures);
} }
vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
{ {
vector<Texture> textures; vector<Texture> textures;
for (UINT i = 0; i < mat->GetTextureCount(type); i++) for (UINT i = 0; i < mat->GetTextureCount(type); i++)
{ {
aiString str; aiString str;
mat->GetTexture(type, i, &str); mat->GetTexture(type, i, &str);
// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
bool skip = false; bool skip = false;
for (UINT j = 0; j < textures_loaded.size(); j++) for (UINT j = 0; j < textures_loaded.size(); j++)
{ {
if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
{ {
textures.push_back(textures_loaded[j]); textures.push_back(textures_loaded[j]);
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization) skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
break; break;
} }
} }
if (!skip) if (!skip)
{ // If texture hasn't been loaded already, load it { // If texture hasn't been loaded already, load it
HRESULT hr; HRESULT hr;
Texture texture; Texture texture;
if (textype == "embedded compressed texture") if (textype == "embedded compressed texture")
{ {
int textureindex = getTextureIndex(&str); int textureindex = getTextureIndex(&str);
texture.texture = getTextureFromModel(scene, textureindex); texture.texture = getTextureFromModel(scene, textureindex);
} }
else else
{ {
string filename = string(str.C_Str()); string filename = string(str.C_Str());
filename = directory + '/' + filename; filename = directory + '/' + filename;
wstring filenamews = wstring(filename.begin(), filename.end()); wstring filenamews = wstring(filename.begin(), filename.end());
hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture); hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
if (FAILED(hr)) if (FAILED(hr))
MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK); MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
} }
texture.type = typeName; texture.type = typeName;
texture.path = str.C_Str(); texture.path = str.C_Str();
textures.push_back(texture); 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. 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; return textures;
} }
void ModelLoader::Close() void ModelLoader::Close()
{ {
for (int i = 0; i < meshes.size(); i++) for (int i = 0; i < meshes.size(); i++)
{ {
meshes[i].Close(); meshes[i].Close();
} }
dev->Release(); dev->Release();
} }
void ModelLoader::processNode(aiNode * node, const aiScene * scene) void ModelLoader::processNode(aiNode * node, const aiScene * scene)
{ {
for (UINT i = 0; i < node->mNumMeshes; i++) for (UINT i = 0; i < node->mNumMeshes; i++)
{ {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(this->processMesh(mesh, scene)); meshes.push_back(this->processMesh(mesh, scene));
} }
for (UINT i = 0; i < node->mNumChildren; i++) for (UINT i = 0; i < node->mNumChildren; i++)
{ {
this->processNode(node->mChildren[i], scene); this->processNode(node->mChildren[i], scene);
} }
} }
string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
{ {
aiString textypeStr; aiString textypeStr;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
string textypeteststr = textypeStr.C_Str(); string textypeteststr = textypeStr.C_Str();
if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
{ {
if (scene->mTextures[0]->mHeight == 0) if (scene->mTextures[0]->mHeight == 0)
{ {
return "embedded compressed texture"; return "embedded compressed texture";
} }
else else
{ {
return "embedded non-compressed texture"; return "embedded non-compressed texture";
} }
} }
if (textypeteststr.find('.') != string::npos) if (textypeteststr.find('.') != string::npos)
{ {
return "textures are on disk"; return "textures are on disk";
} }
} }
int ModelLoader::getTextureIndex(aiString * str) int ModelLoader::getTextureIndex(aiString * str)
{ {
string tistr; string tistr;
tistr = str->C_Str(); tistr = str->C_Str();
tistr = tistr.substr(1); tistr = tistr.substr(1);
return stoi(tistr); return stoi(tistr);
} }
ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
{ {
HRESULT hr; HRESULT hr;
ID3D11ShaderResourceView *texture; ID3D11ShaderResourceView *texture;
int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth); int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture); hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
if (FAILED(hr)) if (FAILED(hr))
MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK); MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
return texture; return texture;
} }

View File

@ -1,44 +1,44 @@
#ifndef MODEL_LOADER_H #ifndef MODEL_LOADER_H
#define MODEL_LOADER_H #define MODEL_LOADER_H
#include <vector> #include <vector>
#include <d3d11_1.h> #include <d3d11_1.h>
#include <DirectXMath.h> #include <DirectXMath.h>
#include <assimp\Importer.hpp> #include <assimp\Importer.hpp>
#include <assimp\scene.h> #include <assimp\scene.h>
#include <assimp\postprocess.h> #include <assimp\postprocess.h>
#include "Mesh.h" #include "Mesh.h"
#include "TextureLoader.h" #include "TextureLoader.h"
using namespace DirectX; using namespace DirectX;
class ModelLoader class ModelLoader
{ {
public: public:
ModelLoader(); ModelLoader();
~ModelLoader(); ~ModelLoader();
bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename); bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
void Draw(ID3D11DeviceContext* devcon); void Draw(ID3D11DeviceContext* devcon);
void Close(); void Close();
private: private:
ID3D11Device *dev; ID3D11Device *dev;
ID3D11DeviceContext *devcon; ID3D11DeviceContext *devcon;
std::vector<Mesh> meshes; std::vector<Mesh> meshes;
string directory; string directory;
vector<Texture> textures_loaded; vector<Texture> textures_loaded;
HWND hwnd; HWND hwnd;
void processNode(aiNode* node, const aiScene* scene); void processNode(aiNode* node, const aiScene* scene);
Mesh processMesh(aiMesh* mesh, const aiScene* scene); Mesh processMesh(aiMesh* mesh, const aiScene* scene);
vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene); vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
string determineTextureType(const aiScene* scene, aiMaterial* mat); string determineTextureType(const aiScene* scene, aiMaterial* mat);
int getTextureIndex(aiString* str); int getTextureIndex(aiString* str);
ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex); ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
}; };
#endif // !MODEL_LOADER_H #endif // !MODEL_LOADER_H

View File

@ -1,55 +1,55 @@
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// File: WICTextureLoader.h // File: WICTextureLoader.h
// //
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it // Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
// (auto-generating mipmaps if possible) // (auto-generating mipmaps if possible)
// //
// Note: Assumes application has already called CoInitializeEx // Note: Assumes application has already called CoInitializeEx
// //
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for // Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
// auto-gen mipmap support. // auto-gen mipmap support.
// //
// Note these functions are useful for images created as simple 2D textures. For // Note these functions are useful for images created as simple 2D textures. For
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. // more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
// For a full-featured DDS file reader, writer, and texture processing pipeline see // For a full-featured DDS file reader, writer, and texture processing pipeline see
// the 'Texconv' sample and the 'DirectXTex' library. // the 'Texconv' sample and the 'DirectXTex' library.
// //
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE. // PARTICULAR PURPOSE.
// //
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// //
// http://go.microsoft.com/fwlink/?LinkId=248926 // http://go.microsoft.com/fwlink/?LinkId=248926
// http://go.microsoft.com/fwlink/?LinkId=248929 // http://go.microsoft.com/fwlink/?LinkId=248929
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma once #pragma once
#endif #endif
#include <d3d11.h> #include <d3d11.h>
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4005) #pragma warning(disable : 4005)
#include <stdint.h> #include <stdint.h>
#pragma warning(pop) #pragma warning(pop)
HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice, HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext, _In_opt_ ID3D11DeviceContext* d3dContext,
_In_bytecount_(wicDataSize) const uint8_t* wicData, _In_bytecount_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize, _In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0
); );
HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice, HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext, _In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName, _In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView, _Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0 _In_ size_t maxsize = 0
); );