title: Assimp can't load other textures except diffuse texture of FBX
body: <p>I try to load the FBX model in the last contains of this <a href="https://learnopengl.com/PBR/IBL/Specular-IBL" rel="nofollow noreferrer">learnopengl tutorial</a>, but I only can load diffuse texture of the FBX. I had tried the solution of adjusting the order of layout in vertex shader, but it didn't work. The result of <code>material-&gt;GetTextureCount(type)</code> is 0 when type isn't <code>aiTextureType_DIFFUSE</code>.
  Here is my code:</p>
  
  <p>mesh.h</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#ifndef Mesh_h
  #define Mesh_h
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;vector&gt;
  using namespace std;
  
  #include &lt;glm/glm.hpp&gt;
  #include &lt;glm/gtc/matrix_transform.hpp&gt;
  #include &lt;glm/gtc/type_ptr.hpp&gt;
  #include "ReviewShader.h"
  struct Vertex{
      glm::vec3 Position;
      glm::vec3 Normal;
      glm::vec2 TexCoord;
  };
  
  struct Texture{
      unsigned int id;
      string type;
      string path;
  };
  
  class Mesh{
  public:
      vector&lt;Texture&gt; textures;
      vector&lt;unsigned int&gt; indices;
      unsigned int VAO;
      Mesh(vector&lt;Vertex&gt; vertices, vector&lt;Texture&gt; textures, vector&lt;unsigned int&gt; indices){
          this-&gt;vertices = vertices;
          this-&gt;textures = textures;
          this-&gt;indices = indices;
  
          setupMesh();
      }
  
      void Draw(ReviewShader shader){
          int diffuseCount = 1;
          int specularCount = 1;
          int reflectionCount = 1;
  
          shader.use();
          for(int i = 0; i &lt; textures.size(); i++){
              string name = textures[i].type;
              string num;
              if(name == "texture_diffuse")
                  num = to_string(diffuseCount++);
              else if(name == "texture_specular")
                  num = to_string(specularCount++);
              else if(name == "texture_reflection")
                  num = to_string(reflectionCount++);
  
              shader.setInt((name+num).c_str(), i);
              glActiveTexture(GL_TEXTURE0+i);
              glBindTexture(GL_TEXTURE_2D, textures[i].id);
          }
          glBindVertexArray(VAO);
          glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
          glActiveTexture(GL_TEXTURE0);
          glBindVertexArray(0);
      }
  private:
      vector&lt;Vertex&gt; vertices;
  
      unsigned int VBO, EBO;
  
      void setupMesh(){
          glGenVertexArrays(1, &amp;VAO);
          glBindVertexArray(VAO);
  
          glGenBuffers(1, &amp;VBO);
          glBindBuffer(GL_ARRAY_BUFFER, VBO);
          glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_STATIC_DRAW);
  
          glGenBuffers(1, &amp;EBO);
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
          glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);
  
          glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
          glEnableVertexAttribArray(0);
          glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
          glEnableVertexAttribArray(1);
          glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoord));
          glEnableVertexAttribArray(2);
  
          glBindVertexArray(0);
      }
  
  };
  #endif /* Mesh_h */
  </code></pre>
  
  <p>model.h</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#ifndef Model_h
  #define Model_h
  
  #include &lt;iostream&gt;
  using namespace std;
  
  #include &lt;string&gt;
  
  #include &lt;vector&gt;
  #include "Mesh.h"
  #include "ReviewShader.h"
  
  #include &lt;glm/glm.hpp&gt;
  #include &lt;glm/gtc/matrix_transform.hpp&gt;
  #include &lt;glm/gtc/type_ptr.hpp&gt;
  
  #include &lt;assimp/Importer.hpp&gt;
  #include &lt;assimp/scene.h&gt;
  #include &lt;assimp/postprocess.h&gt;
  
  //#define STB_IMAGE_IMPLEMENTATION
  #include &lt;stb-master/stb_image.h&gt;
  vector&lt;Texture&gt; loaded_textures;
  
  class Model{
  public:
      vector&lt;Mesh&gt; meshes;
      string directory;
  
      Model(char *path){
          loadModel(path);
      }
      void Draw(ReviewShader shader){
          for(int i = 0; i &lt; meshes.size(); i++){
              meshes[i].Draw(shader);
          }
      }
  private:
      void loadModel(string path){
          Assimp::Importer importer;
  //        const aiScene *scene = importer.ReadFile(path, aiProcess_FlipUVs | aiProcess_Triangulate);
          const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
          if(!scene || scene-&gt;mFlags &amp; AI_SCENE_FLAGS_INCOMPLETE || !scene-&gt;mRootNode){
              cout &lt;&lt; "ERROR::ASSIMP::" &lt;&lt; importer.GetErrorString() &lt;&lt; endl;
              return;
          }
          directory = path.substr(0, path.find_last_of("/"));
          processNode(scene-&gt;mRootNode, scene);
  
      }
  
      void processNode(aiNode *node, const aiScene *scene){
          for(int i = 0; i &lt; node-&gt;mNumMeshes; i++){
              aiMesh *mesh = scene-&gt;mMeshes[node-&gt;mMeshes[i]];
              meshes.push_back(processMesh(mesh, scene));
          }
          for(int i = 0; i &lt; node-&gt;mNumChildren; i++){
              processNode(node-&gt;mChildren[i], scene);
          }
      }
  
      Mesh processMesh(aiMesh *mesh, const aiScene *scene){
          vector&lt;Vertex&gt; vertices;
          vector&lt;Texture&gt; textures;
          vector&lt;unsigned int&gt; indices;
  
          for(int i = 0; i &lt; mesh-&gt;mNumVertices; i++){
              Vertex vertex;
              glm::vec3 vector;
              vector.x = mesh-&gt;mVertices[i].x;
              vector.y = mesh-&gt;mVertices[i].y;
              vector.z = mesh-&gt;mVertices[i].z;
              vertex.Position = vector;
  
              vector.x = mesh-&gt;mNormals[i].x;
              vector.y = mesh-&gt;mNormals[i].y;
              vector.z = mesh-&gt;mNormals[i].z;
              vertex.Normal = vector;
  
              if(mesh-&gt;mTextureCoords[0]){
                  glm::vec2 tex;
                  tex.x = mesh-&gt;mTextureCoords[0][i].x;
                  tex.y = mesh-&gt;mTextureCoords[0][i].y;
                  vertex.TexCoord = tex;
              }
              else{
                  vertex.TexCoord = glm::vec2(0.0, 0.0);
              }
              vertices.push_back(vertex);
          }
  
          for(int i = 0; i &lt; mesh-&gt;mNumFaces; i++){
              aiFace face = mesh-&gt;mFaces[i];
              for(int j = 0; j &lt; face.mNumIndices; j++){
                  indices.push_back(face.mIndices[j]);
              }
          }
  
          aiMaterial *material = scene-&gt;mMaterials[mesh-&gt;mMaterialIndex];
          vector&lt;Texture&gt; texture_diffuse = loadMaterialTexture(material, aiTextureType_DIFFUSE, "texture_diffuse");
          textures.insert(textures.end(), texture_diffuse.begin(), texture_diffuse.end());
          vector&lt;Texture&gt; texture_specular = loadMaterialTexture(material, aiTextureType_SPECULAR, "texture_specular");
          textures.insert(textures.end(), texture_specular.begin(), texture_specular.end());
          vector&lt;Texture&gt; texture_ambient = loadMaterialTexture(material, aiTextureType_SHININESS, "texture_reflection");
          textures.insert(textures.end(), texture_ambient.begin(), texture_ambient.end());
          return Mesh(vertices, textures, indices);
  
      }
  
      vector&lt;Texture&gt; loadMaterialTexture(aiMaterial *material, aiTextureType type, string Typename){
          vector&lt;Texture&gt; textures;
          cout &lt;&lt; material-&gt;GetTextureCount(type) &lt;&lt; endl;
          for(int i = 0; i &lt; material-&gt;GetTextureCount(type); i++){
              bool skip = false;
              aiString str;
              material-&gt;GetTexture(type, i, &amp;str);
              string tempStr = str.C_Str();
              tempStr.replace(tempStr.find("\\"), 1, "/");
              cout &lt;&lt; tempStr &lt;&lt; endl;
  
              for(int j = 0; j &lt; loaded_textures.size(); j++){
                  if(strcmp(loaded_textures[j].path.c_str(), tempStr.c_str()) == 0){
                      skip = true;
                      textures.push_back(loaded_textures[i]);
                      break;
                  }
              }
  
              if(!skip){
                  Texture tex;
                  tex.id = loadTextureFromFile(tempStr, directory);
                  tex.type = Typename;
                  tex.path = str.C_Str();
                  textures.push_back(tex);
                  loaded_textures.push_back(tex);
              }
          }
          return textures;
      }
  
      unsigned int loadTextureFromFile(string path, string &amp;Directory){
          unsigned int textureID;
          glGenTextures(1, &amp;textureID);
          glBindTexture(GL_TEXTURE_2D, textureID);
  
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
          string filepath = Directory + "/" + path;
          int width, height, urChannel;
          unsigned char *data = stbi_load(filepath.c_str(), &amp;width, &amp;height, &amp;urChannel, 0);
          if(data){
              GLenum format;
              if(urChannel == 1)
                  format = GL_RED;
              if(urChannel == 3)
                  format = GL_RGB;
              if(urChannel == 4)
                  format = GL_RGBA;
              glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
              glGenerateMipmap(GL_TEXTURE_2D);
              stbi_image_free(data);
          }
          else{
              cout &lt;&lt; "Read texture Data failed\n";
              stbi_image_free(data);
          }
          return textureID;
      }
  };
  #endif /* Model_h */
  </code></pre>
  
  <p>model.vs</p>
  
  <pre class="lang-c prettyprint-override"><code>#version 330 core
  layout(location = 0) in vec3 aPos;
  layout(location = 1) in vec3 aNormal;
  layout(location = 2) in vec2 aUV;
  
  uniform mat4 model;
  uniform mat4 view;
  uniform mat4 projection;
  
  out vec3 Normal;
  out vec2 UV;
  out vec3 Position;
  
  void main(){
      gl_Position = projection * view * model * vec4(aPos, 1.0);
      UV = aUV;
      Normal = mat3(transpose(inverse(model))) * aNormal;
      Position = vec3(model * vec4(aPos, 1.0));    
  }
  </code></pre>
  
  <p>model.fs</p>
  
  <pre class="lang-c prettyprint-override"><code>#version 330 core
  out vec4 FragColor;
  
  uniform sampler2D texture_diffuse;
  uniform sampler2D texture_specular;
  uniform sampler2D texture_roughness;
  
  in vec3 Normal;
  in vec2 UV;
  in vec3 Position;
  
  void main(){
      FragColor = texture(texture_diffuse, UV);
  }
  </code></pre>
  
  <p>main.cpp</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;...&gt;
  ...
  using namespace std;
  
  
  void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  void mouse_callback(GLFWwindow* window, double xpos, double ypos);
  void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
  void processInput(GLFWwindow *window);
  unsigned int loadTexture(const char *path);
  unsigned int loadHDRTexture(char const * path);
  unsigned int loadCubemap(vector&lt;string&gt; faces);
  void renderQuad();
  void renderCube();
  void renderPlane();
  void renderSphere();
  float lerp(float a, float b, float scale);
  // size settings
  const unsigned int SCR_WIDTH = 800;
  const unsigned int SCR_HEIGHT = 600;
  
  glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0);
  glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7);
  
  // calculation parameter
  const float Pi = 3.14159265359;
  const float doublePi = Pi * 2.0;
  
  
  // camera
  Camera camera(glm::vec3(0.0f, 0.0f, 10.0f));
  float lastX = (float)SCR_WIDTH  / 2.0;
  float lastY = (float)SCR_HEIGHT / 2.0;
  bool firstMouse = true;
  
  // timing
  float deltaTime = 0.0f;
  float lastFrame = 0.0f;
  
  // texture normal
  glm::vec3 normal(0.0, 0.0, 1.0);
  
  // plane normal
  glm::vec3 planeNormal = glm::vec3(0.0, 1.0, 0.0);
  
  
  int main()
  {
      // glfw: initialize and configure
      // ------------------------------
      ...   
  
      // Create shaders
      ...
      ReviewShader modelShader("shader/model.vs", "shader/model.fs");
  
      // pbr configure
      ...
  
      Model gunModel = Model("Gun_Model/Cerberus_LP.FBX");
  
      while(!glfwWindowShouldClose(window))
      {
          // avoid delay
          // -----------
          float currentFrame = glfwGetTime();
          deltaTime = currentFrame - lastFrame;
          lastFrame = currentFrame;
  
          // process input
          // -------------
          processInput(window);
          glViewport(0, 0, SCR_WIDTH * 2, SCR_HEIGHT * 2);
          glClearColor(1.0, 1.0, 1.0, 1.0);
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
          glm::mat4 model = glm::mat4(1.0);
          glm::mat4 view = camera.getViewMatrix();
          glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
  
          modelShader.use();
          model = glm::mat4(1.0);
          model = glm::scale(model, glm::vec3(0.1));
          model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0, 0.0, 0.0));
          modelShader.setMat4("model", model);
          modelShader.setMat4("view", view);
          modelShader.setMat4("projection", projection);
          gunModel.Draw(modelShader);
  
          glfwSwapBuffers(window);
          glfwPollEvents();
      }
  
      glfwTerminate();
      return 0;
  }
  </code></pre>