示例#1
0
// 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());
	}

}