Assimp 无法加载除 FBX 的漫反射纹理之外的其他纹理

Assimp can't load other textures except diffuse texture of FBX

本文关键字:纹理 漫反射 其他 FBX 加载 Assimp      更新时间:2023-10-16

我尝试在本教程的最后一部分加载FBX模型,但我只能加载FBX的漫反射纹理。我尝试过在顶点着色器中调整布局顺序的解决方案,但没有成功。当类型不是aiTextureType_DIFFUSE时,material->GetTextureCount(type)的结果为0。这是我的代码:

网格.h

#ifndef Mesh_h
#define Mesh_h
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#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<Texture> textures;
vector<unsigned int> indices;
unsigned int VAO;
Mesh(vector<Vertex> vertices, vector<Texture> textures, vector<unsigned int> indices){
this->vertices = vertices;
this->textures = textures;
this->indices = indices;
setupMesh();
}
void Draw(ReviewShader shader){
int diffuseCount = 1;
int specularCount = 1;
int reflectionCount = 1;
shader.use();
for(int i = 0; i < 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<Vertex> vertices;
unsigned int VBO, EBO;
void setupMesh(){
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &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 */

型号.h

#ifndef Model_h
#define Model_h
#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include "Mesh.h"
#include "ReviewShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
//#define STB_IMAGE_IMPLEMENTATION
#include <stb-master/stb_image.h>
vector<Texture> loaded_textures;
class Model{
public:
vector<Mesh> meshes;
string directory;
Model(char *path){
loadModel(path);
}
void Draw(ReviewShader shader){
for(int i = 0; i < 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->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
directory = path.substr(0, path.find_last_of("/"));
processNode(scene->mRootNode, scene);
}
void processNode(aiNode *node, const aiScene *scene){
for(int i = 0; i < node->mNumMeshes; i++){
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for(int i = 0; i < node->mNumChildren; i++){
processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh *mesh, const aiScene *scene){
vector<Vertex> vertices;
vector<Texture> textures;
vector<unsigned int> indices;
for(int i = 0; i < mesh->mNumVertices; i++){
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if(mesh->mTextureCoords[0]){
glm::vec2 tex;
tex.x = mesh->mTextureCoords[0][i].x;
tex.y = mesh->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 < mesh->mNumFaces; i++){
aiFace face = mesh->mFaces[i];
for(int j = 0; j < face.mNumIndices; j++){
indices.push_back(face.mIndices[j]);
}
}
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> texture_diffuse = loadMaterialTexture(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), texture_diffuse.begin(), texture_diffuse.end());
vector<Texture> texture_specular = loadMaterialTexture(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), texture_specular.begin(), texture_specular.end());
vector<Texture> texture_ambient = loadMaterialTexture(material, aiTextureType_SHININESS, "texture_reflection");
textures.insert(textures.end(), texture_ambient.begin(), texture_ambient.end());
return Mesh(vertices, textures, indices);
}
vector<Texture> loadMaterialTexture(aiMaterial *material, aiTextureType type, string Typename){
vector<Texture> textures;
cout << material->GetTextureCount(type) << endl;
for(int i = 0; i < material->GetTextureCount(type); i++){
bool skip = false;
aiString str;
material->GetTexture(type, i, &str);
string tempStr = str.C_Str();
tempStr.replace(tempStr.find("\"), 1, "/");
cout << tempStr << endl;
for(int j = 0; j < 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 &Directory){
unsigned int textureID;
glGenTextures(1, &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(), &width, &height, &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 << "Read texture Data failedn";
stbi_image_free(data);
}
return textureID;
}
};
#endif /* Model_h */

型号.vs

#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));    
}

型号fs

#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);
}

main.cpp

#include <...>
...
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<string> 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;
}

首先:您使用哪个版本的资产导入器库?我们在FBX导入器中做了很多改进,因此强烈建议切换到最新的5.0版本。

通常,当纹理数量显示为零时,这表明我们的模型中只使用了一个纹理。为了验证您是否可以使用Blender、内部资产导入器查看器或Godot引擎的编辑器来检查您的模型是否正确。

如果你的模型中存储的不仅仅是漫反射纹理,请在这里创建一个新的问题报告:Assimp Bugtracker。请添加一个模型,我们可以使用它来重现这个问题。提前感谢!

我也遇到了这个问题。

我使用win 10的3D Viewer来查看除了反照率纹理之外没有其他纹理,所以问题不在于ASSIMP,而在于Cerberus_LP.FBX文件。您可以手动绑定纹理,就像它们在";纹理;文件夹。

此外,如果有人想使用3D Viewer检查纹理,只需用程序打开对象,然后单击右侧面板中的中间选项卡,中间选项卡会显示";Stats&着色";。