我正在尝试为项目设置一个简单的OpenGL框架,但遇到显示.obj模型对象的问题。据我所知,正在使用assimp
很好地加载了对象,应该将所有网格物体都绘制到屏幕上,但是我什么都没看到。
我将引导您完成从加载.obj到绘制它的整个过程。首先,我们需要了解一些文件:
main.cxx
int main()
{
Display display(800, 600, "project2");
Model model("./models/nanosuit/nanosuit.obj");
Shader shader("./shaders/shader");
Texture texture("./textures/wall.jpg");
int width, height;
glfwGetWindowSize(display.GetWindow(), &width, &height);
Camera camera(glm::vec3(0, 0, -5.0f), 45.0f, (float)width/height, 0.1f, 1000.0f);
Transform transform;
while (!display.IsClosed())
{
display.ProcessInput();
display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
shader.Bind();
texture.Bind(0);
shader.Update(transform, camera);
model.Draw();
display.Update();
}
return 0;
}
Shader :: Update()
void Shader::Update(const Transform& transform, const Camera& camera)
{
glm::mat4 trans = camera.GetViewProjection() * transform.GetModel();
glUniformMatrix4fv(uniforms[TRANSFORM_U], 1, GL_FALSE, &trans[0][0]);
}
顶点着色器
#version 330 core
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
layout (location=2) in vec3 normal;
out vec2 texCoord0;
out vec3 normal0;
uniform mat4 transform;
void main() {
gl_Position = transform * vec4(position, 1.0);
texCoord0 = texCoord;
normal0 = (transform * vec4(normal, 0.0)).xyz;
}
片段着色器
#version 330 core
out vec4 FragColor;
uniform sampler2D diffuse;
in vec2 texCoord0;
in vec3 normal0;
void main() {
FragColor = texture(diffuse, texCoord0);
}
我首先将模型加载到我的Model类的构造函数中
Model model("./models/nanosuit/nanosuit.obj");
model.cxx
Model::Model(const std::string& filePath)
{
Assimp::Importer import;
const aiScene *scene = import.ReadFile(filePath, aiProcess_Triangulate | aiProcess_FlipUVs);
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
return;
}
//directory = filePath.substr(0, filePath.find_last_of('/'));
processNode(scene->mRootNode, scene);
}
void Model::Draw()
{
for (unsigned int i = 0; i < meshes.size(); ++i)
meshes[i].Draw();
}
void Model::processNode(aiNode *node, const aiScene *scene)
{
for (unsigned int i = 0; i < node->mNumMeshes; ++i)
{
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++)
{
processNode(node->mChildren[i], scene);
}
}
Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
{
glm::vec3 position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
glm::vec2 texCoords = glm::vec2(0.0f);
if(mesh->mTextureCoords[0])
texCoords = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
glm::vec3 normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
Vertex vertex(position, texCoords, normal);
vertices.push_back(vertex);
}
// process indices
for(unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
return Mesh(&vertices[0], vertices.size(), &indices[0], indices.size());
}
依次创建一个网格列表,然后通过调用
在屏幕上绘制网格 Model::Draw()
这是我的网格物体类,供您参考
mesh.cxx
Mesh::Mesh(Vertex *vertices, unsigned int numVertices, unsigned int* indices, unsigned int numIndices)
{
std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoords;
std::vector<glm::vec3> normals;
for (unsigned int i = 0; i < numVertices; ++i)
{
positions.push_back(vertices[i].GetPos());
texCoords.push_back(vertices[i].GetTexCoord());
normals.push_back(vertices[i].GetNormal());
}
drawCount = numIndices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(NUM_BUFFERS, VBO);
// positions
glBindBuffer(GL_ARRAY_BUFFER, VBO[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(positions[0]), &positions[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// texCoords
glBindBuffer(GL_ARRAY_BUFFER, VBO[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
// normals
glBindBuffer(GL_ARRAY_BUFFER, VBO[NORMAL_VB]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(normals[0]), &normals[0], GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
// indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO[INDEX_VB]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(indices[0]), &indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &VAO);
}
void Mesh::Draw()
{
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
我已经验证了网格顶点实际上是由Mesh :: Draw()方法接收的,应该绘制它们。但是,再次在窗口中没有输出:(