diff --git a/Editor/resources/Shaders/atmospheric_sky.shader b/Editor/resources/Shaders/atmospheric_sky.shader index 369b8d71..b58713b2 100644 --- a/Editor/resources/Shaders/atmospheric_sky.shader +++ b/Editor/resources/Shaders/atmospheric_sky.shader @@ -121,7 +121,7 @@ vec3 scatter(vec3 o, vec3 d, float L, vec3 Lo) { I_R = I_M = vec3(0.); // Compute T(P -> O) and I_M and I_R - scatterIn(o, d, L, 16.); + scatterIn(o, d, L, 32.); // mu = cos(alpha) float mu = dot(d, SunDirection); @@ -141,16 +141,18 @@ uniform mat4 View; void main() { // Might add camera position in here. + // It was already in there, I removed it. vec3 O = vec3(0., 0., 0.); vec2 NDC = UV * 2.0 - 1; - - vec4 camSpace = inverse(Projection * View) * vec4(vec3(NDC, 1.0), 1.0); + mat4 newView = View; + newView[3] = vec4(0,0,0,1); + vec4 camSpace = inverse(Projection * newView) * vec4(vec3(NDC, 1.0), 1.0); vec3 direction = normalize(camSpace.xyz); vec3 D = direction; - vec3 col = vec3(1.0); + vec3 col = vec3(0.0); float L = escape(O, D, AtmosphereRadius); col = scatter(O, D, L, col); FragColor = vec4(col, 1.); diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 56310b4b..e28db125 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -287,40 +287,317 @@ namespace Nuake { if (ImGui::Begin("Environnement")) { const Ref env = Engine::GetCurrentScene()->GetEnvironment(); - if (ImGui::CollapsingHeader("Procedural Sky", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::DragFloat("Sun Intensity", &env->ProceduralSkybox->SunIntensity, 0.1f, 0.0f); - Vector3 currentDirection = env->ProceduralSkybox->SunDirection; - ImGuiHelper::DrawVec3("Sun Direction", ¤tDirection); - env->ProceduralSkybox->SunDirection = glm::normalize(currentDirection); + if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner)) + { + ImGui::TableSetupColumn("name", 0, 0.3); + ImGui::TableSetupColumn("set", 0, 0.6); + ImGui::TableSetupColumn("reset", 0, 0.1); - Vector3 mieScattering = env->ProceduralSkybox->MieScattering * 10000.0f; - ImGuiHelper::DrawVec3("Mie Scattering", &mieScattering); - env->ProceduralSkybox->MieScattering = mieScattering / 10000.0f; - } - if (ImGui::CollapsingHeader("HDR", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::DragFloat("Exposure", &env->Exposure, .01f, 0.0f, 10.0f); - ImGui::DragFloat("Gamma", &env->Gamma, 0.1f, 0.0f, 10.0f); - } - if (ImGui::CollapsingHeader("Bloom", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Checkbox("Enabled", &env->BloomEnabled); - float threshold = env->mBloom->GetThreshold(); - ImGui::DragFloat("Threshold", &threshold, 0.01f, 0.0f, 500.0f); - env->mBloom->SetThreshold(threshold); + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Sky Type"); + ImGui::TableNextColumn(); - int iteration = env->mBloom->GetIteration(); - ImGui::DragInt("Iteration", &iteration, 1.0f, 0, 8); - env->mBloom->SetIteration(iteration); + // Here we create a dropdown for every sky type. + const char* SkyTypes[] = { "Procedural Sky", "Color" }; + static int currentSkyType = (int)env->CurrentSkyType; + ImGui::Combo("##SkyType", ¤tSkyType, SkyTypes, IM_ARRAYSIZE(SkyTypes)); + env->CurrentSkyType = (SkyType)currentSkyType; + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string ResetType = ICON_FA_UNDO + std::string("##ResetType"); + if (ImGui::Button(ResetType.c_str())) env->CurrentSkyType = SkyType::ProceduralSky; + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + if(env->CurrentSkyType == SkyType::ClearColor) + { + // Title + ImGui::Text("Clear color"); + ImGui::TableNextColumn(); + + // Color picker + ImGui::ColorEdit4("##clearColor", &env->AmbientColor.r, ImGuiColorEditFlags_NoAlpha); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetColor = ICON_FA_UNDO + std::string("##ResetColor"); + if (ImGui::Button(resetColor.c_str())) env->AmbientColor = Color(0, 0, 0, 1); + ImGui::PopStyleColor(); + } + + else if (env->CurrentSkyType == SkyType::ProceduralSky) + { + + { // Sun Intensity + ImGui::Text("Sun Intensity"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("##Sun Intensity", &env->ProceduralSkybox->SunIntensity, 0.1f, 0.0f, 1000.0f); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetSunIntensity = ICON_FA_UNDO + std::string("##ResetSunIntensity"); + if (ImGui::Button(resetSunIntensity.c_str())) env->ProceduralSkybox->SunIntensity = 100.0f; + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Sun Direction + ImGui::Text("Sun Direction"); + ImGui::TableNextColumn(); + + Vector3 sunDirection = env->ProceduralSkybox->GetSunDirection(); + ImGuiHelper::DrawVec3("##Sun Direction", &sunDirection); + env->ProceduralSkybox->SunDirection = glm::normalize(sunDirection); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetSunDirection = ICON_FA_UNDO + std::string("##resetSunDirection"); + if (ImGui::Button(resetSunDirection.c_str())) env->ProceduralSkybox->SunDirection = Vector3(0.20000f, 0.95917f, 0.20000f); + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Surface Radius + ImGui::Text("Surface Radius"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("##surfaceRadius", &env->ProceduralSkybox->SurfaceRadius, 100.f, 0.0f); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetSurfaceRadius = ICON_FA_UNDO + std::string("##resetSurfaceRadius"); + if (ImGui::Button(resetSurfaceRadius.c_str())) env->ProceduralSkybox->SurfaceRadius = 6360e3f; + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Atmosphere Radius + ImGui::Text("Atmosphere Radius"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("##AtmosphereRadius", &env->ProceduralSkybox->AtmosphereRadius, 100.f, 0.0f); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetAtmosphereRadius = ICON_FA_UNDO + std::string("##resetAtmosphereRadius"); + if (ImGui::Button(resetAtmosphereRadius.c_str())) env->ProceduralSkybox->AtmosphereRadius = 6380e3f; + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Center point + ImGui::Text("Center Point"); + ImGui::TableNextColumn(); + + ImGuiHelper::DrawVec3("##Center Point", &env->ProceduralSkybox->CenterPoint, 0.0f, 100.0f, 100.0f); + ImGui::TableNextColumn(); + if (env->ProceduralSkybox->CenterPoint.y < -env->ProceduralSkybox->AtmosphereRadius) + env->ProceduralSkybox->CenterPoint.y = -env->ProceduralSkybox->AtmosphereRadius + 1.f; + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetCenterPoint = ICON_FA_UNDO + std::string("##resetAtmosphereRadius"); + if (ImGui::Button(resetCenterPoint.c_str())) env->ProceduralSkybox->CenterPoint = Vector3(0, -env->ProceduralSkybox->AtmosphereRadius, 0); + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Mie Scattering + ImGui::Text("Mie Scattering"); + ImGui::TableNextColumn(); + + Vector3 mieScattering = env->ProceduralSkybox->MieScattering * 10000.0f; + ImGuiHelper::DrawVec3("##Mie Scattering", &mieScattering, 0.0f, 100.0f, 0.01f); + if (mieScattering.x < 0) mieScattering.x = 0; + if (mieScattering.y < 0) mieScattering.y = 0; + if (mieScattering.z < 0) mieScattering.z = 0; + env->ProceduralSkybox->MieScattering = mieScattering / 10000.0f; + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetMieScattering = ICON_FA_UNDO + std::string("##resetMieScattering"); + if (ImGui::Button(resetMieScattering.c_str())) env->ProceduralSkybox->MieScattering = Vector3(2e-5f); + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // RayleighScattering + ImGui::Text("Rayleigh Scattering"); + ImGui::TableNextColumn(); + + Vector3 rayleighScattering = env->ProceduralSkybox->RayleighScattering * 10000.0f; + ImGuiHelper::DrawVec3("##Ray Scattering", &rayleighScattering, 0.0f, 100.0f, 0.01f); + if (rayleighScattering.r < 0) rayleighScattering.r = 0; + if (rayleighScattering.g < 0) rayleighScattering.g = 0; + if (rayleighScattering.b < 0) rayleighScattering.b = 0; + env->ProceduralSkybox->RayleighScattering = rayleighScattering / 10000.0f; + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetRayScattering = ICON_FA_UNDO + std::string("##resetRayScattering"); + if (ImGui::Button(resetRayScattering.c_str())) env->ProceduralSkybox->RayleighScattering = Vector3(58e-7f, 135e-7f, 331e-7f); + ImGui::PopStyleColor(); + } + } + + ImGui::TableNextColumn(); + { // Exposure + ImGui::Text("Exposure"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("Exposure", &env->Exposure, .01f, 0.0f, 100.0f); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetExposure = ICON_FA_UNDO + std::string("##resetExposure"); + if (ImGui::Button(resetExposure.c_str())) env->Exposure = 3.5f; + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { // Gamma + ImGui::Text("Gamma"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("Gamma", &env->Gamma, 0.1f, 0.0f, 10.0f); + ImGui::TableNextColumn(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetGamma = ICON_FA_UNDO + std::string("##resetGamma"); + if (ImGui::Button(resetGamma.c_str())) env->Gamma = 1.1f; + ImGui::PopStyleColor(); + } + + ImGui::EndTable(); } - if (ImGui::CollapsingHeader("Fog", ImGuiTreeNodeFlags_DefaultOpen)) + + + + if (ImGui::CollapsingHeader("Post processing", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Enabled", &env->VolumetricEnabled); - ImGui::DragFloat("Volumetric Scattering", &env->VolumetricFog, .01f, 0.0f, 1.0f); - ImGui::DragFloat("Volumetric Step Count", &env->VolumetricStepCount, 1.f, 0.0f); + if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner)) + { + ImGui::TableSetupColumn("name", 0, 0.3); + ImGui::TableSetupColumn("set", 0, 0.6); + ImGui::TableSetupColumn("reset", 0, 0.1); + + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Bloom"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##Enabled", &env->BloomEnabled); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetBloom = ICON_FA_UNDO + std::string("##resetBloom"); + if (ImGui::Button(resetBloom.c_str())) env->BloomEnabled = false; + ImGui::PopStyleColor(); + } + + if (env->BloomEnabled) + { + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Bloom Threshold"); + ImGui::TableNextColumn(); + + float threshold = env->mBloom->GetThreshold(); + ImGui::DragFloat("##Threshold", &threshold, 0.01f, 0.0f, 500.0f); + env->mBloom->SetThreshold(threshold); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetBloomThreshold"); + if (ImGui::Button(resetBloomThreshold.c_str())) env->mBloom->SetThreshold(2.4f); + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Bloom Quality"); + ImGui::TableNextColumn(); + + int iteration = env->mBloom->GetIteration(); + ImGui::DragInt("##quality", &iteration, 1.0f, 0, 4); + env->mBloom->SetIteration(iteration); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetQuality = ICON_FA_UNDO + std::string("##resetQuality"); + if (ImGui::Button(resetQuality.c_str())) env->mBloom->SetIteration(3); + ImGui::PopStyleColor(); + } + } + + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Volumetric"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##VolumetricEnabled", &env->VolumetricEnabled); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetVolumetric = ICON_FA_UNDO + std::string("##resetVolumetric"); + if (ImGui::Button(resetVolumetric.c_str())) env->VolumetricEnabled = false; + ImGui::PopStyleColor(); + } + + if (env->VolumetricEnabled) + { + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Volumetric Scattering"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("##Volumetric Scattering", &env->VolumetricFog, .01f, 0.0f, 1.0f); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetBloomThreshold"); + if (ImGui::Button(resetBloomThreshold.c_str())) env->mBloom->SetThreshold(2.4f); + ImGui::PopStyleColor(); + } + + ImGui::TableNextColumn(); + { + // Title + ImGui::Text("Step count"); + ImGui::TableNextColumn(); + + ImGui::DragFloat("##Volumetric Step Count", &env->VolumetricStepCount, 1.f, 0.0f); + ImGui::TableNextColumn(); + + // Reset button + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0)); + std::string resetQuality = ICON_FA_UNDO + std::string("##resetQuality"); + if (ImGui::Button(resetQuality.c_str())) env->VolumetricStepCount = 50.f; + ImGui::PopStyleColor(); + } + } + + } + ImGui::EndTable(); + } + if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::DragFloat("Exposure", &Engine::GetCurrentScene()->m_EditorCamera->Exposure, .01f, 0.0f, 5.0f); diff --git a/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp b/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp index c1224068..abf92dc0 100644 --- a/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp +++ b/Nuake/src/Rendering/Platforms/OGLRendererAPI.cpp @@ -19,7 +19,7 @@ namespace Nuake { void OGLRendererAPI::SetClearColor(const Color& color) { - glClearColor(color.r, color.g, color.g, color.a); + glClearColor(color.r, color.g, color.b, color.a); } void OGLRendererAPI::GenBuffer(unsigned int& bufferID) diff --git a/Nuake/src/Rendering/SceneRenderer.cpp b/Nuake/src/Rendering/SceneRenderer.cpp index 789b8d09..627cbfc7 100644 --- a/Nuake/src/Rendering/SceneRenderer.cpp +++ b/Nuake/src/Rendering/SceneRenderer.cpp @@ -68,12 +68,11 @@ namespace Nuake { { mVolumetric->Resize(framebuffer.GetSize()); mVolumetric->SetDepth(mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get()); - mVolumetric->Draw(mProjection, mView, lightList); + mVolumetric->Draw(mProjection , mView, lightList); finalOutput = mVolumetric->GetFinalOutput(); } - // Copy final output to target framebuffer framebuffer.Bind(); { @@ -191,7 +190,16 @@ namespace Nuake { RenderCommand::Disable(RendererEnum::DEPTH_TEST); RenderCommand::Disable(RendererEnum::FACE_CULL); - scene.GetEnvironment()->ProceduralSkybox->Draw(mProjection, mView); + Ref environment = scene.GetEnvironment(); + if (environment->CurrentSkyType == SkyType::ProceduralSky) + { + environment->ProceduralSkybox->Draw(mProjection, mView); + } + else if (environment->CurrentSkyType == SkyType::ClearColor) + { + RenderCommand::SetClearColor(environment->AmbientColor); + RenderCommand::Clear(); + } RenderCommand::Enable(RendererEnum::FACE_CULL); Shader* shadingShader = ShaderManager::GetShader("resources/Shaders/deferred.shader"); diff --git a/Nuake/src/Rendering/Textures/Texture.cpp b/Nuake/src/Rendering/Textures/Texture.cpp index 679aa539..c2be1aad 100644 --- a/Nuake/src/Rendering/Textures/Texture.cpp +++ b/Nuake/src/Rendering/Textures/Texture.cpp @@ -57,6 +57,8 @@ namespace Nuake glTexImage2D(GL_TEXTURE_2D, 0, format2, size.x, size.y, 0, format, format3, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); //glGenerateMipmap(GL_TEXTURE_2D); } diff --git a/Nuake/src/Scene/Entities/ImGuiHelper.h b/Nuake/src/Scene/Entities/ImGuiHelper.h index 1a193465..4c01dfb8 100644 --- a/Nuake/src/Scene/Entities/ImGuiHelper.h +++ b/Nuake/src/Scene/Entities/ImGuiHelper.h @@ -7,7 +7,7 @@ class ImGuiHelper { public: - static void DrawVec3(const std::string label, glm::vec3* values, float resetValue = 0.0f, float columnWidth = 100.0) { + static void DrawVec3(const std::string label, glm::vec3* values, float resetValue = 0.0f, float columnWidth = 100.0, float rate = 0.1f, float min = 0.0f) { ImGuiIO& io = ImGui::GetIO(); auto boldFont = io.Fonts->Fonts[0]; @@ -30,7 +30,7 @@ public: ImGui::SameLine(); ImGui::PushItemWidth(availWidth); - ImGui::DragFloat("##X", &values->x, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::DragFloat("##X", &values->x, rate, min, 0.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::SameLine(); @@ -44,7 +44,7 @@ public: ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::PushItemWidth(availWidth); - ImGui::DragFloat("##Y", &values->y, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::DragFloat("##Y", &values->y, rate, 0.0f, 0.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::SameLine(); @@ -59,7 +59,7 @@ public: ImGui::SameLine(); ImGui::PushItemWidth(availWidth); - ImGui::DragFloat("##Z", &values->z, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::DragFloat("##Z", &values->z, rate, 0.0f, 0.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::PopStyleVar(); diff --git a/Nuake/src/Scene/Lighting/Environment.cpp b/Nuake/src/Scene/Lighting/Environment.cpp index 46ee889b..e79bab26 100644 --- a/Nuake/src/Scene/Lighting/Environment.cpp +++ b/Nuake/src/Scene/Lighting/Environment.cpp @@ -30,6 +30,7 @@ namespace Nuake { json Environment::Serialize() { BEGIN_SERIALIZE(); + SERIALIZE_VAL(CurrentSkyType); SERIALIZE_VAL(VolumetricFog); SERIALIZE_VAL(VolumetricStepCount); SERIALIZE_VEC4(AmbientColor); @@ -40,7 +41,8 @@ namespace Nuake { bool Environment::Deserialize(const std::string& str) { BEGIN_DESERIALIZE(); - + if (j.contains("CurrentSkyType")) + CurrentSkyType = j["CurrentSkyType"]; if (j.contains("VolumetricFog")) VolumetricFog = j["VolumetricFog"]; if (j.contains("VolumetricStepCount")) diff --git a/Nuake/src/Scene/Lighting/Environment.h b/Nuake/src/Scene/Lighting/Environment.h index 706168a1..d17519a2 100644 --- a/Nuake/src/Scene/Lighting/Environment.h +++ b/Nuake/src/Scene/Lighting/Environment.h @@ -9,10 +9,22 @@ namespace Nuake { + enum class SkyType { + ProceduralSky = 0, + ClearColor = 1 + // CubeMap + }; + class Environment : public ISerializable { public: Environment(); + + SkyType CurrentSkyType = SkyType::ClearColor; + + Color AmbientColor = Color(0, 0, 0, 1); + Ref ProceduralSkybox; + bool VolumetricEnabled = false; float VolumetricFog = 0.90f; float VolumetricStepCount = 50.f; @@ -24,9 +36,6 @@ namespace Nuake Scope mBloom; Vector3 ClearColor; - glm::vec4 AmbientColor; - Ref ProceduralSkybox; - glm::vec4 m_AmbientColor; glm::vec4 GetAmbientColor(); void SetAmbientColor(glm::vec4 color);