#include "CGL430Material.h" #include "CWindowManager.h" #include "COpenGL430Renderer.h" #include "CEngine.h" #include "CScopeExit.h" #include "CImage.h" #include "CResourcesManager.h" #include "U_String.h" #include "U_Files.h" #include namespace //local space (scope) { COpenGL430Renderer* GetRenderer() { if(CEngine::GetInstance()->GetStopFlag()) { return nullptr; } CWindowManager* winman = CEngine::GetInstance()->Components.GetComponentTyped(); if(!winman) { return nullptr; } return dynamic_cast(winman->Renderer.get()); } } CGL430Material::CGL430Material() { auto renderer = GetRenderer(); if(renderer) { renderer->RegisterMaterial(this); } } CGL430Material::~CGL430Material() { auto renderer = GetRenderer(); if(renderer) { renderer->UnregisterMaterial(this); glMakeTextureHandleNonResidentARB(DiffuseTextureHandle); glDeleteTextures(1, &DiffuseTextureNativeHandle); } } bool CGL430Material::V_Load(const std::filesystem::path& path) { std::shared_ptr diffuseTexture; auto resman = CEngine::GetInstance()->Components.GetComponentTyped(); auto& time = CEngine::GetInstance()->Time; auto found_path = FileUtils::find_first_by_name(FileUtils::get_executable_path() / "resources" / "materials", path.string()); if(!found_path.has_value()) { return false; } std::ifstream objfile(found_path.value()); if (!objfile.is_open()) { return false; } CScopeExit streamExiter([&objfile]() { objfile.close(); }); std::string ReadLine; while (!objfile.eof()) { std::getline(objfile, ReadLine, '\n'); std::vector splitted; StringUtils::split_str(ReadLine, ' ', splitted); std::string cmd = splitted[0]; std::string param = StringUtils::merge_arg(splitted, 1, splitted.size() - 1); //Log::Instance() << "Parsed material property \"" << cmd << "\": \"" << param << "\"\n"; LOGLOG if(cmd == "texture") { //Log::Instance() << "Loading texture " << param << Log::Endl; LOGLOG auto res = resman->LoadResource("image", param); diffuseTexture = std::dynamic_pointer_cast(res); CTimePoint now = CEngine::GetInstance()->Time.GetCurrent(); CTimePoint expires = TIME_EXPR(now + std::chrono::seconds(5)); resman->Cache.Add(res, expires); glGenTextures(1, &DiffuseTextureNativeHandle); glBindTexture(GL_TEXTURE_2D, DiffuseTextureNativeHandle); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, diffuseTexture->GetSize().x, diffuseTexture->GetSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, diffuseTexture->GetRawData()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); DiffuseTextureHandle = glGetTextureHandleARB(DiffuseTextureNativeHandle); glMakeTextureHandleResidentARB(DiffuseTextureHandle); } else if(cmd == "diffuse") { DiffuseColor = StringUtils::FromStr(param); } else if(cmd == "shininess") { Shininess = StringUtils::FromStr(param); } } Log::Instance() << "Material done loading with handles " << DiffuseTextureHandle << " and " << DiffuseTextureNativeHandle << "\n"; return true; } std::shared_ptr CGL430Material::CreatePipelineContext(const std::filesystem::path& path) { return std::make_shared(this, path); } void CGL430Material::V_SetupLoadPipeline(CLoadPipeline& pipeline) { pipeline.push_back //load material data (async) ( { [](std::shared_ptr context) -> bool { auto resman = CEngine::GetInstance()->Components.GetComponentTyped(); auto& time = CEngine::GetInstance()->Time; auto matContext = std::dynamic_pointer_cast(context); auto thisMaterial = dynamic_cast(context->CurrentResource); auto& path = context->LoadPath; auto found_path = FileUtils::find_first_by_name(FileUtils::get_executable_path() / "resources" / "materials", path.string()); if(!found_path.has_value()) { return false; } std::ifstream objfile(found_path.value()); if (!objfile.is_open()) { return false; } CScopeExit streamExiter([&objfile]() { objfile.close(); }); std::string ReadLine; while (!objfile.eof()) { std::getline(objfile, ReadLine, '\n'); std::vector splitted; StringUtils::split_str(ReadLine, ' ', splitted); std::string cmd = splitted[0]; std::string param = StringUtils::merge_arg(splitted, 1, splitted.size() - 1); //Log::Instance() << "Parsed material property \"" << cmd << "\": \"" << param << "\"\n"; //LOGLOG if(cmd == "texture") { matContext->DiffusePath = param; //Log::Instance() << "Loading texture " << param << Log::Endl; //LOGLOG auto img = resman->GetOrCreate("image", param); context->RequiredResources.push_back(img); //img->Wait(); NO WAITING IN ASYNC THREAD } else if(cmd == "diffuse") { thisMaterial->DiffuseColor = StringUtils::FromStr(param); } else if(cmd == "shininess") { thisMaterial->Shininess = StringUtils::FromStr(param); } } return true; }, true //async (is_async) } ); pipeline.push_back //upload image to gpu (sync) ( { [](std::shared_ptr context) -> bool { auto resman = CEngine::GetInstance()->Components.GetComponentTyped(); auto matContext = std::dynamic_pointer_cast(context); auto thisMaterial = dynamic_cast(context->CurrentResource); std::shared_ptr _res = nullptr; for(auto res : context->RequiredResources) { //Log::Instance() << "Required res " << res->Name << " with status of " << (int)res->LoadingStatus << Log::Endl; if(res->Name == matContext->DiffusePath.stem().string() && res->LoadingStatus == CResource::CLoadingStatus::Done) { _res = res; break; } } if(!_res) { //Log::ErrInstance() << "NO RES FOR UPLOAD " << matContext->DiffusePath.stem().string() << Log::Endl; return false; } auto diffuseTexture = std::dynamic_pointer_cast(_res); //&thisMaterial->DiffuseTextureNativeHandle glGenTextures(1, &thisMaterial->DiffuseTextureNativeHandle); glBindTexture(GL_TEXTURE_2D, thisMaterial->DiffuseTextureNativeHandle); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, diffuseTexture->GetSize().x, diffuseTexture->GetSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, diffuseTexture->GetRawData()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); thisMaterial->DiffuseTextureHandle = glGetTextureHandleARB(thisMaterial->DiffuseTextureNativeHandle); glMakeTextureHandleResidentARB(thisMaterial->DiffuseTextureHandle); //Log::Instance() << "Uploaded image to gpu\n"; //LOGLOG return true; }, false //sync (is_async) } ); } LINK_RESOURCE_TO_CLASS(CGL430Material, gl430material)