Loading normal maps from files

Started by
0 comments, last by TomKQT 9 years, 11 months ago

Hey, today I'll show you how to load normal maps from any file format (I'll assume you're using assimp which supports most of the popular model formats.)

The problem with most of the formats is that they don't support more than 1 texture per subset in model, so the solution to this problem is using a prefix or different extension for normal maps and other maps and then getting normal map from the name of diffuse map. I use _NRM prefix for normal maps and _OCC prefix for Ambient Occlusion maps.

Here is my code (NOTE: your diffuse map and normal map must have same name but different prefix/extension i.e your diffuse map is brick.dds and your normal map for it is brick_NRM.dds/bricks.nmap or whatever.)


 
 
static std::string removeExtension(std::string filename) {
    size_t lastdot = filename.find_last_of(".");
    if (lastdot == std::string::npos) return filename;
    return filename.substr(0, lastdot); 
}
 
//.............
if (Mat->GetTextureCount(aiTextureType_DIFFUSE) > 0 && Mat->GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS)
{
 
   std::string file = path.C_Str();
   std::string NoExtension = removeExtension(file);
std::string newName = NoExtension + ".dds";
newName = "Resources\\Textures\\" + newName;
 
 
ID3D11ShaderResourceView* srv = mInfo.Mgr->CreateTexture(newName);
 
DiffuseMapSRV.push_back(srv);
}
 
 
std::string file = path.C_Str();
std::string NoExtension = removeExtension(file);
 
std::string NormalMapTexturePath = NoExtension + "_NRM"; //add normal map prefix
NormalMapTexturePath = NormalMapTexturePath + ".dds"; //add extension
 
std::string AmbientOcclusionMapTexturePath = NoExtension + "_OCC"; //add occlusion map prefix
AmbientOcclusionMapTexturePath = AmbientOcclusionMapTexturePath + ".dds"; //add extension
 
//finally add full path
 
NormalMapTexturePath = "Resources\\Textures\\" + NormalMapTexturePath;
AmbientOcclusionMapTexturePath = "Resources\\Textures\\" + AmbientOcclusionMapTexturePath;
 
ID3D11ShaderResourceView* srv = mInfo.Mgr->CreateTexture(NormalMapTexturePath);
NormalMapSRV.push_back(srv);
 
if (AOMap)
{
srv = mInfo.Mgr->CreateTexture(AmbientOcclusionMapTexturePath);
   AOMapSRV.push_back(srv);
}
Advertisement

The problem with most of the formats is that they don't support more than 1 texture per subset in model, so the solution to this problem is using a prefix or different extension for normal maps and other maps and then getting normal map from the name of diffuse map.

I encountered too many limitations of the standard file formats (1 texture per subset is the most basic one), so after some work-around solutions I finaly decided to create my own mesh file format ;) Now I can store all the material properties I want.

Or it also could be a good idea to separate the mesh data (vertices, indices etc.) from the actual look (material) and have two files for each mesh. I think the Source engine uses this approach? Not sure.

In the material file, which can have the same name as the mesh file to be able to match them together, you can have a detailed description of the effects, textures, colors and all other properties (even LODs, physical properties for physics engine...) related to each mesh.

EDIT: here's how Valve's doing it: https://developer.valvesoftware.com/wiki/Material

This topic is closed to new replies.

Advertisement