// Assuming the metallic-roughness material model of models loaded with GLTF. std::pair<ID, std::vector<std::pair<Texture::Type, std::string>>> MeshManager::load_mesh(const std::string& directory, const std::string& file) { MeshInformation mesh_info; mesh_info.loaded_from_filepath = directory + file; Assimp::Importer importer; auto scene = importer.ReadFile(mesh_info.loaded_from_filepath.c_str(), aiProcess_Triangulate | aiProcess_JoinIdenticalVertices); if (scene == nullptr || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) { Log::error(std::string(importer.GetErrorString())); return {0, {}}; } std::vector<std::pair<Texture::Type, std::string>> texture_info; if (scene->HasMaterials()) { Log::info("Number of materials: " + std::to_string(scene->mNumMaterials)); for (size_t i = 0; i < scene->mNumMaterials; i++) { auto material = scene->mMaterials[i]; aiString material_name; material->Get(AI_MATKEY_NAME, material_name); Log::info("Material name: " + std::string(material_name.C_Str())); aiString diffuse_filepath; if (material->GetTexture(aiTextureType_DIFFUSE, 0, &diffuse_filepath) == AI_SUCCESS) { Log::info("Diffuse texture name: " + std::string(directory.c_str()) + std::string(diffuse_filepath.data)); std::string texture_filepath(diffuse_filepath.data); texture_filepath.insert(0, directory); texture_info.push_back({Texture::Type::Diffuse, texture_filepath}); } aiString specular_filepath; if (material->GetTexture(aiTextureType_SPECULAR, 0, &specular_filepath) == AI_SUCCESS) { Log::info("Specular texture name: " + std::string(directory.c_str()) + std::string(specular_filepath.data)); } aiString ambient_filepath; if (material->GetTexture(aiTextureType_AMBIENT, 0, &ambient_filepath) == AI_SUCCESS) { Log::info("Ambient occlusion texture name: " + std::string(directory.c_str()) + std::string(ambient_filepath.data)); } aiString shininess_filepath; if (material->GetTexture(aiTextureType_SHININESS, 0, &shininess_filepath) == AI_SUCCESS) { Log::info("Shininess texture name: " + std::string(directory.c_str()) + std::string(shininess_filepath.data)); } aiString emissive_filepath; if (material->GetTexture(aiTextureType_EMISSIVE, 0, &emissive_filepath) == AI_SUCCESS) { Log::info("Emissive texture name: " + std::string(directory.c_str()) + std::string(emissive_filepath.data)); std::string texture_filepath(emissive_filepath.data); texture_filepath.insert(0, directory); texture_info.push_back({Texture::Type::Emissive, texture_filepath}); // TODO: Fetch emissive factor as well } aiString displacement_filepath; if (material->GetTexture(aiTextureType_DISPLACEMENT, 0, &displacement_filepath) == AI_SUCCESS) { Log::info("Displacement texture name: " + std::string(directory.c_str()) + std::string(displacement_filepath.data)); } aiString height_filepath; if (material->GetTexture(aiTextureType_HEIGHT, 0, &height_filepath) == AI_SUCCESS) { Log::info("Bumpmap texture name: " + std::string(directory.c_str()) + std::string(height_filepath.data)); } // Lightmap is usually the ambient occlusion map ... aiString lightmap_filepath; if (material->GetTexture(aiTextureType_LIGHTMAP, 0, &lightmap_filepath) == AI_SUCCESS) { Log::info("Lightmap texture name: " + std::string(directory.c_str()) + std::string(lightmap_filepath.data)); std::string texture_filepath(lightmap_filepath.data); texture_filepath.insert(0, directory); texture_info.push_back({Texture::Type::AmbientOcclusion, texture_filepath}); } aiString normals_filepath; if (material->GetTexture(aiTextureType_NORMALS, 0, &normals_filepath) == AI_SUCCESS) { Log::info("Normals texture name: " + std::string(directory.c_str()) + std::string(normals_filepath.data)); } aiString reflection_filepath; if (material->GetTexture(aiTextureType_REFLECTION, 0, &reflection_filepath) == AI_SUCCESS) { Log::info("Reflection texture name: " + std::string(directory.c_str()) + std::string(reflection_filepath.data)); } aiString opacity_filepath; if (material->GetTexture(aiTextureType_OPACITY, 0, &opacity_filepath) == AI_SUCCESS) { Log::info("Opacity texture name: " + std::string(directory.c_str()) + std::string(opacity_filepath.data)); } // NOTE: Roughness metallic textures are not detected so here we are assuming this is the unknown texture of the material. aiString unknown_filepath; if (material->GetTexture(aiTextureType_UNKNOWN, 0, &unknown_filepath) == AI_SUCCESS) { Log::info("Unknown texture name: " + std::string(directory.c_str()) + std::string(unknown_filepath.data)); std::string texture_filepath(normals_filepath.data); texture_filepath.insert(0, directory); texture_info.push_back({Texture::Type::MetallicRoughness, texture_filepath}); } } } if (scene->HasMeshes()) { // FIXME: Assumes the mesh is a single mesh and not a hierarchy Log::info("Scene: # meshes " + std::to_string(scene->mNumMeshes)); for (size_t i = 0; i < scene->mNumMeshes; i++) { auto mesh = scene->mMeshes[i]; Log::info("Loading mesh with name: " + std::string(mesh->mName.data)); for (size_t j = 0; j < mesh->mNumVertices; j++) { Vertex vertex; auto pos = mesh->mVertices[j]; vertex.position = {pos.x, pos.y, pos.z}; if (mesh->HasTextureCoords(0)) { auto tex_coord = mesh->mTextureCoords[0][j]; vertex.tex_coord = {tex_coord.x, -tex_coord.y}; // glTF (& .obj) has a flipped texture coordinate system compared to OpenGL } if (mesh->HasNormals()) { auto normal = mesh->mNormals[j]; vertex.normal = {normal.x, normal.y, normal.z}; } mesh_info.mesh.vertices.push_back(vertex); } for (size_t j = 0; j < mesh->mNumFaces; j++) { auto face = &mesh->mFaces[j]; if (face->mNumIndices != 3) { Log::warn("Not 3 vertices per face in model."); return {0, {}}; } for (size_t k = 0; k < 3; k++) { auto index = face->mIndices[k]; mesh_info.mesh.indices.push_back(index); } } } } // FIXME: Mesh id is worthless since it does not change or anything ... loaded_meshes.push_back(mesh_info.mesh); return {loaded_meshes.size() - 1, texture_info}; }
void FrameBufferDemo::Initialize() { fboProgram.AddShaderFile(ShaderType::Vertex,"Assets/Shaders/Vertex/fbo.vert"); fboProgram.AddShaderFile(ShaderType::Fragment,"Assets/Shaders/Fragment/fbo.frag"); fboProgram.Build(); textureProgram.AddShaderFile(ShaderType::Vertex, "Assets/Shaders/Vertex/texture.vert"); textureProgram.AddShaderFile(ShaderType::Fragment, "Assets/Shaders/Fragment/texture.frag"); textureProgram.Build(); textureProgram.AddUniformBlock({ "TransformBlock", { { "TransformBlock.view", &camera->GetView()[0][0], sizeof(camera->GetView()) }, { "TransformBlock.projection", &camera->GetProjection()[0][0], sizeof(camera->GetProjection()) }, } }); fboProgram.AddUniformBlock({ "TransformBlock",{ { "TransformBlock.view", &camera->GetView()[0][0], sizeof(camera->GetView()) }, { "TransformBlock.projection", &camera->GetProjection()[0][0], sizeof(camera->GetProjection()) }, } }); input->addBinding(GLFW_KEY_LEFT, [this](InputInfo info) { camera->MoveLeft(); fboProgram.UpdateUniformBlock("TransformBlock"); textureProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_RIGHT, [this](InputInfo info) { camera->MoveRight(); fboProgram.UpdateUniformBlock("TransformBlock"); textureProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_UP, [this](InputInfo info) { camera->MoveForward(); textureProgram.UpdateUniformBlock("TransformBlock"); fboProgram.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_DOWN, [this](InputInfo info) { camera->MoveBack(); textureProgram.UpdateUniformBlock("TransformBlock"); fboProgram.UpdateUniformBlock("TransformBlock"); }); glGenFramebuffers(1, &fboHandle); glBindFramebuffer(GL_FRAMEBUFFER, fboHandle); glGenTextures(1, &renderTargetTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, renderTargetTexture); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 512, 512); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTargetTexture,0); glGenRenderbuffers(1, &depthBufferTexture); glBindRenderbuffer(GL_RENDERBUFFER, depthBufferTexture); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 512, 512); GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, drawBufs); glBindFramebuffer(GL_FRAMEBUFFER, 0); Assimp::Importer importer; auto cubeScene = importer.ReadFile("Assets/Models/Obj/box.obj", aiProcess_Triangulate); cube = std::unique_ptr<GameObject>(new GameObject()); cube->GetTransform()->SetPosition({ 0.0f,0.0f,-5.0f }); cube->GetTransform()->SetScale({ 20.0f,20.0f,20.0f }); cube->Update(); if (cubeScene && cubeScene->HasMeshes()) { cubeMesh = std::unique_ptr<MeshComponent>(new MeshComponent(cube.get())); cubeMesh->Initialize(cubeScene->mMeshes[0], fboProgram, { {"world", UniformType::MAT4, &cube->GetWorld()[0][0]}, }); cubeMesh->AddTexture({ renderTargetTexture,GL_TEXTURE_2D, renderer->GetSampler(SamplerType::Linear).sampler }); } auto monkeyScene = importer.ReadFile("Assets/Models/Obj/monkey.obj", aiProcess_Triangulate); monkey = std::unique_ptr<GameObject>(new GameObject()); monkey->GetTransform()->SetPosition({ 2.0f,0.0f,-2.0f }); monkey->Update(); if (monkeyScene && monkeyScene->HasMeshes()) { monkeyMesh = std::unique_ptr<MeshComponent>(new MeshComponent(monkey.get())); monkeyMesh->Initialize(monkeyScene->mMeshes[0], textureProgram, { {"world", UniformType::MAT4, &monkey->GetWorld()[0][0]} }); monkeyMesh->AddTexture("Assets/Textures/brick.jpg"); } importer.FreeScene(); }
void NormalMapDemo::Initialize() { glEnable(GL_DEPTH_TEST); program.AddShaderFile(ShaderType::Vertex, "Assets/Shaders/Vertex/normal-map.vert"); program.AddShaderFile(ShaderType::Fragment, "Assets/Shaders/Fragment/normal-map.frag"); program.Build(); light.position = glm::vec3(0.0f, 0.0f, 1.0f); light.color = glm::vec3(0.8f,0.8f,0.8f); program.AddUniformBlock({ "TransformBlock",{ { "TransformBlock.view",&camera->GetView()[0][0], sizeof(camera->GetView()) }, {"TransformBlock.projection",&camera->GetProjection()[0][0], sizeof(camera->GetProjection()) }, {"TransformBlock.eyePosition", &camera->GetPosition()[0], sizeof(camera->GetPosition())} } }); program.AddUniformBlock({ "LightBlock", { { "LightBlock.position", &light.position[0], sizeof(light.position) }, {"LightBlock.color", &light.color[0], sizeof(light.color)}, } }); ogre = std::unique_ptr<GameObject>(new GameObject()); ogre->GetTransform()->SetPosition({ 0.0f,0.0f,-3.0f }); ogre->Update(); input->addBinding(GLFW_KEY_LEFT, [this](InputInfo info) { camera->MoveLeft(); program.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_RIGHT, [this](InputInfo info) { camera->MoveRight(); program.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_UP, [this](InputInfo info) { camera->MoveForward(); program.UpdateUniformBlock("TransformBlock"); }); input->addBinding(GLFW_KEY_DOWN, [this](InputInfo info) { camera->MoveBack(); program.UpdateUniformBlock("TransformBlock"); }); Assimp::Importer importer; auto scene = importer.ReadFile("Assets/Models/Obj/ogre.obj", aiProcess_Triangulate | aiProcess_CalcTangentSpace ); if (scene && scene->HasMeshes()) { mesh = std::unique_ptr<MeshComponent>(new MeshComponent(ogre.get())); mesh->Initialize(scene->mMeshes[0], program, { {"world",UniformType::MAT4, &ogre->GetWorld()[0][0]}, { "material.ambient", UniformType::VEC3, &mesh->GetMaterial().ambient[0] }, {"material.specular", UniformType::VEC4, &mesh->GetMaterial().specular[0]}, }); mesh->GetMaterial().ambient = glm::vec3(0.5f, 0.5f, 0.5f); mesh->GetMaterial().specular = glm::vec4(.4f, .2f, .7f,4.0f); mesh->AddTexture("Assets/Textures/ogre_diffuse.png"); mesh->AddTexture("Assets/Textures/ogre_normal.png"); ogre->AddComponent(mesh.get()); } }