Sign in to follow this  
newtechnology

Loading normal maps from files

Recommended Posts

newtechnology    1955

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);
}
Edited by newtechnology

Share this post


Link to post
Share on other sites
Tom KQT    1704

 

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

Edited by Tom KQT

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this