diff --git a/Source/Core/Editor/Widgets/CMakeLists.txt b/Source/Core/Editor/Widgets/CMakeLists.txt index b362046ddb..147922d73a 100644 --- a/Source/Core/Editor/Widgets/CMakeLists.txt +++ b/Source/Core/Editor/Widgets/CMakeLists.txt @@ -50,6 +50,7 @@ target_link_libraries(Widgets ERS_STRUCT_HardwareInfo ERS_STRUCT_Scene ERS_STRUCT_ProjectUtils + ERS_STRUCT_RendererSettings ERS_SceneManager diff --git a/Source/Core/Editor/Widgets/GUI_Widget_ObjectProperties.cpp b/Source/Core/Editor/Widgets/GUI_Widget_ObjectProperties.cpp index 9b1fd572ae..22a08e4b66 100644 --- a/Source/Core/Editor/Widgets/GUI_Widget_ObjectProperties.cpp +++ b/Source/Core/Editor/Widgets/GUI_Widget_ObjectProperties.cpp @@ -116,7 +116,9 @@ void Widget_ObjectProperties::Draw() { ImGui::SameLine(); ImGui::HelpMarker("Sets the distance after which the scene is no longer affected by this light source."); - + ImGui::Checkbox("Cast Shadows", &SceneManager_->Scenes_[SceneManager_->ActiveScene_]->PointLights[Index]->CastsShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Allows or disallows this light from creating shadows on the scene."); } @@ -142,6 +144,9 @@ void Widget_ObjectProperties::Draw() { ImGui::SameLine(); ImGui::HelpMarker("Sets the distance after which the scene is no longer affected by this light source."); + ImGui::Checkbox("Cast Shadows", &SceneManager_->Scenes_[SceneManager_->ActiveScene_]->DirectionalLights[Index]->CastsShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Allows or disallows this light from creating shadows on the scene."); } @@ -179,6 +184,33 @@ void Widget_ObjectProperties::Draw() { ImGui::SameLine(); ImGui::HelpMarker("Sets the angle at which the outer cone begins to roll off. This angle sets the inner cone which is unaffected by rolloff. Rolloff occurs in the area between the outer and inner cone (this angle)."); + ImGui::Checkbox("Cast Shadows", &SceneManager_->Scenes_[SceneManager_->ActiveScene_]->SpotLights[Index]->CastsShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Allows or disallows this light from creating shadows on the scene."); + + } + + } else if (SceneManager_->Scenes_[SceneManager_->ActiveScene_]->SceneObjects_[SelectedSceneObject].Type_ == std::string("Model")) { + + unsigned long Index = SceneManager_->Scenes_[SceneManager_->ActiveScene_]->SceneObjects_[SelectedSceneObject].Index_; + if (ImGui::CollapsingHeader("Model Settings", ImGuiTreeNodeFlags_DefaultOpen)) { + + // Get Current Model + ERS_STRUCT_Model* Model = SceneManager_->Scenes_[SceneManager_->ActiveScene_]->Models[Index].get(); + + ImGui::Checkbox("Casts Dynamic Shadows", &Model->CastDynamicShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Indicates if this model will cast shadows in dynamic lights. Avoid using this whenever possible due to performance related issues."); + + ImGui::Checkbox("Casts Static Shadows", &Model->CastStaticShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Indicates if this model will cast shadows in static lights."); + + ImGui::Checkbox("Receive Shadows", &Model->ReceiveShadows_); + ImGui::SameLine(); + ImGui::HelpMarker("Allow this model to have shadows cast upon it by other objects as well as itself."); + + } } diff --git a/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.cpp b/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.cpp index 4f281f06d2..f8cd4df228 100644 --- a/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.cpp +++ b/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.cpp @@ -13,9 +13,31 @@ Widget_RenderingSettings::Widget_RenderingSettings(ERS_STRUCT_SystemUtils* Syste SystemUtils_->Logger_->Log("Setting Up Default Renderer Setting Input Fields", 3); SystemUtils_->Logger_->Log("Copying Shadow Map Resolution", 2); - DepthMapResolution_[0] = SystemUtils_->RendererSettings_->ShadowMapX_; - DepthMapResolution_[1] = SystemUtils_->RendererSettings_->ShadowMapY_; + ERS_STRUCT_RendererSettings* Settings = SystemUtils_->RendererSettings_.get(); + DepthMapResolution_[0] = Settings->ShadowMapX_; + DepthMapResolution_[1] = Settings->ShadowMapY_; + + if (Settings->ShadowFilteringType_ == ERS::Renderer::ERS_SHADOW_FILTERING_DISABLED) { + SelectedShadowFiltering_ = 0; + } else if (Settings->ShadowFilteringType_ == ERS::Renderer::ERS_SHADOW_FILTERING_PCF) { + SelectedShadowFiltering_ = 1; + } else if (Settings->ShadowFilteringType_ == ERS::Renderer::ERS_SHADOW_FILTERING_POISSON_SAMPLING) { + SelectedShadowFiltering_ = 2; + } else if (Settings->ShadowFilteringType_ == ERS::Renderer::ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING) { + SelectedShadowFiltering_ = 3; + } + if (Settings->ShadowUpdateMode_ == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISABLED) { + SelectedShadowUpdates_ = 0; + } else if (Settings->ShadowUpdateMode_ == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_RANDOM) { + SelectedShadowUpdates_ = 1; + } else if (Settings->ShadowUpdateMode_ == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_CONSECUTIVE) { + SelectedShadowUpdates_ = 2; + } else if (Settings->ShadowUpdateMode_ == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED) { + SelectedShadowUpdates_ = 3; + } else if (Settings->ShadowUpdateMode_ == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_ALL) { + SelectedShadowUpdates_ = 4; + } } @@ -103,14 +125,62 @@ void Widget_RenderingSettings::Draw() { ImGui::Separator(); ImGui::Spacing(); bool Apply = false; + ERS_STRUCT_RendererSettings* Settings = SystemUtils_->RendererSettings_.get(); + + const char* ShadowFilteringNames[] = { + "ERS_SHADOW_FILTERING_DISABLED", + "ERS_SHADOW_FILTERING_PCF", + "ERS_SHADOW_FILTERING_POISSON_SAMPLING", + "ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING" + }; + const char* ShadowUpdateNames[] = { + "ERS_SHADOW_UPDATE_MODE_DISABLED", + "ERS_SHADOW_UPDATE_MODE_RANDOM", + "ERS_SHADOW_UPDATE_MODE_CONSECUTIVE", + "ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED", + "ERS_SHADOW_UPDATE_MODE_ALL" + }; + + + // Draw Buttons/Input Fields ImGui::InputInt2("Depth Map Resolution", DepthMapResolution_); - Apply = ImGui::Button("Apply"); + ImGui::InputInt("Max Shadow Updates Per Frame", &Settings->MaxShadowUpdatesPerFrame_); + ImGui::InputInt("Shadow Filter Kernel Size", &Settings->ShadowFilterKernelSize_); + + ImGui::Combo("Shadow Filtering", &SelectedShadowFiltering_, ShadowFilteringNames, 4); + ImGui::Combo("Shadow Update Mode", &SelectedShadowUpdates_, ShadowUpdateNames, 5); + + // Handle Apply Button + Apply = ImGui::Button("Apply"); if (Apply) { - SystemUtils_->RendererSettings_->ShadowMapX_ = DepthMapResolution_[0]; - SystemUtils_->RendererSettings_->ShadowMapY_ = DepthMapResolution_[1]; + Settings->ShadowMapX_ = DepthMapResolution_[0]; + Settings->ShadowMapY_ = DepthMapResolution_[1]; + + if (SelectedShadowFiltering_ == 0) { + Settings->ShadowFilteringType_ = ERS::Renderer::ERS_SHADOW_FILTERING_DISABLED; + } else if (SelectedShadowFiltering_ == 1) { + Settings->ShadowFilteringType_ = ERS::Renderer::ERS_SHADOW_FILTERING_PCF; + } else if (SelectedShadowFiltering_ == 2) { + Settings->ShadowFilteringType_ = ERS::Renderer::ERS_SHADOW_FILTERING_POISSON_SAMPLING; + } else if (SelectedShadowFiltering_ == 3) { + Settings->ShadowFilteringType_ = ERS::Renderer::ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING; + } + + if (SelectedShadowUpdates_ == 0) { + Settings->ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISABLED; + } else if (SelectedShadowUpdates_ == 1) { + Settings->ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_RANDOM; + } else if (SelectedShadowUpdates_ == 2) { + Settings->ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_CONSECUTIVE; + } else if (SelectedShadowUpdates_ == 3) { + Settings->ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED; + } else if (SelectedShadowUpdates_ == 4) { + Settings->ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_ALL; + } + } diff --git a/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.h b/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.h index ba3c2ea3df..a6d1c11bbb 100644 --- a/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.h +++ b/Source/Core/Editor/Widgets/GUI_Widget_RenderingSettings.h @@ -16,6 +16,10 @@ // Internal Libraries (BG convention: use <> instead of "") #include +#include + +#include +#include @@ -34,11 +38,12 @@ class Widget_RenderingSettings { // Variables To Store Input Data int DepthMapResolution_[2]; /**>Stores the value that the user is putting into the depth map input box*/ - + int SelectedShadowFiltering_ = 0; + int SelectedShadowUpdates_ = 0; public: - bool Enabled_ = false; /** Model) { @@ -229,6 +230,13 @@ void ERS_CLASS_ModelLoader::ProcessGPU(std::shared_ptr Model) // Process Texture References, Setup Meshes for (unsigned long i = 0; i < Model->Meshes.size(); i++) { + + // Set Shadow Configuration Pointers + Model->Meshes[i].CastDynamicShadows_ = &Model->CastDynamicShadows_; + Model->Meshes[i].CastStaticShadows_ = &Model->CastStaticShadows_; + Model->Meshes[i].ReceiveShadows_ = &Model->ReceiveShadows_; + + for (unsigned long Index = 0; Index < Model->Meshes[i].TextureReferences_.size(); Index++) { // IF TEXTURES DONT WORK, CHECK HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! int TextureIndex = Model->Meshes[i].TextureReferences_[Index]; diff --git a/Source/Core/Loader/ERS_SceneLoader/ERS_SceneLoader.cpp b/Source/Core/Loader/ERS_SceneLoader/ERS_SceneLoader.cpp index 35db10cfd5..6ecbfc6ba6 100644 --- a/Source/Core/Loader/ERS_SceneLoader/ERS_SceneLoader.cpp +++ b/Source/Core/Loader/ERS_SceneLoader/ERS_SceneLoader.cpp @@ -113,6 +113,19 @@ ERS_STRUCT_Scene ERS_CLASS_SceneLoader::ProcessScene(YAML::Node RawSceneData, lo } + // Load Shadow Configuration + if (SceneDataNode[i]["CastDynamicShadows"]) { + Scene.Models[CurrentSize-1]->CastDynamicShadows_ = SceneDataNode[i]["CastDynamicShadows"].as(); + } + + if (SceneDataNode[i]["CastStaticShadows"]) { + Scene.Models[CurrentSize-1]->CastStaticShadows_ = SceneDataNode[i]["CastStaticShadows"].as(); + } + + if (SceneDataNode[i]["ReceiveShadows"]) { + Scene.Models[CurrentSize-1]->ReceiveShadows_ = SceneDataNode[i]["ReceiveShadows"].as(); + } + } else if (AssetType == std::string("DirectionalLight")) { @@ -149,6 +162,11 @@ ERS_STRUCT_Scene ERS_CLASS_SceneLoader::ProcessScene(YAML::Node RawSceneData, lo SceneDataNode[i]["RotZ"].as() ); + + if (SceneDataNode[i]["CastShadows"]) { + Scene.DirectionalLights[LightIndex]->CastsShadows_ = SceneDataNode[i]["CastShadows"].as(); + } + // Load Attached Scripts if (SceneDataNode[i]["AttachedScripts"]) { YAML::Node Scripts = SceneDataNode[i]["AttachedScripts"]; @@ -186,6 +204,10 @@ ERS_STRUCT_Scene ERS_CLASS_SceneLoader::ProcessScene(YAML::Node RawSceneData, lo SceneDataNode[i]["PosZ"].as() ); + if (SceneDataNode[i]["CastShadows"]) { + Scene.PointLights[LightIndex]->CastsShadows_ = SceneDataNode[i]["CastShadows"].as(); + } + // Load Attached Scripts if (SceneDataNode[i]["AttachedScripts"]) { YAML::Node Scripts = SceneDataNode[i]["AttachedScripts"]; @@ -234,6 +256,10 @@ ERS_STRUCT_Scene ERS_CLASS_SceneLoader::ProcessScene(YAML::Node RawSceneData, lo ); + if (SceneDataNode[i]["CastShadows"]) { + Scene.SpotLights[LightIndex]->CastsShadows_ = SceneDataNode[i]["CastShadows"].as(); + } + // Load Attached Scripts if (SceneDataNode[i]["AttachedScripts"]) { YAML::Node Scripts = SceneDataNode[i]["AttachedScripts"]; @@ -272,6 +298,20 @@ void ERS_CLASS_SceneLoader::AddModel(ERS_STRUCT_Scene* Scene, long AssetID) { Scene->Models[CurrentSize-1]->Name = std::string("Loading..."); Scene->Models[CurrentSize-1]->FlipTextures = true; + + // Process Texture References, Setup Meshes + ERS_STRUCT_Model* Model = Scene->Models[CurrentSize-1].get(); + for (unsigned long i = 0; i < Model->Meshes.size(); i++) { + + // Set Shadow Configuration Pointers + Model->Meshes[i].CastDynamicShadows_ = &Model->CastDynamicShadows_; + Model->Meshes[i].CastStaticShadows_ = &Model->CastStaticShadows_; + Model->Meshes[i].ReceiveShadows_ = &Model->ReceiveShadows_; + + + } + + ModelLoader_->AddModelToLoadingQueue(AssetID, Scene->Models[CurrentSize-1], Scene->Models[CurrentSize-1]->FlipTextures); diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/CMakeLists.txt b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/CMakeLists.txt index 2b314d4333..b8b192e166 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/CMakeLists.txt +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/CMakeLists.txt @@ -23,6 +23,8 @@ add_library(ERS_CLASS_VisualRenderer "ERS_FUNCTION_DrawMeshNoTextures.cpp" "ERS_FUNCTION_ResetMeshTexture.cpp" "ERS_FUNCTION_ConvertRotationToFrontVector.cpp" + "ERS_FUNCTION_MeshTransparencySortNoTextures.cpp" + # Add Header Files (.h) @@ -42,6 +44,8 @@ add_library(ERS_CLASS_VisualRenderer "ERS_FUNCTION_DrawMeshNoTextures.h" "ERS_FUNCTION_ResetMeshTexture.h" "ERS_FUNCTION_ConvertRotationToFrontVector.h" + "ERS_FUNCTION_MeshTransparencySortNoTextures.h" + @@ -77,6 +81,7 @@ target_link_libraries(ERS_CLASS_VisualRenderer ERS_STRUCT_Scene ERS_STRUCT_ProjectUtils ERS_STRUCT_OpenGLDefaults + ERS_STRUCT_RendererSettings ) diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.cpp b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.cpp index c617f7ed6b..276ea1f1b3 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.cpp +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.cpp @@ -16,6 +16,7 @@ ERS_CLASS_DepthMaps::ERS_CLASS_DepthMaps(ERS_STRUCT_SystemUtils* SystemUtils, ER // Create Array Texture For Depth Maps RegenerateDepthMapTextureArray2D(16, SystemUtils_->RendererSettings_->ShadowMapX_, SystemUtils_->RendererSettings_->ShadowMapY_); RegenerateDepthMapTextureArrayCubemap(2); + glGenFramebuffers(1, &PointLightClearFBO_); } @@ -208,26 +209,34 @@ bool ERS_CLASS_DepthMaps::RegenerateDepthMapTextureArrayCubemap(int NumberOfText bool ERS_CLASS_DepthMaps::FreeDepthMapIndex2D(unsigned int Index) { + SystemUtils_->Logger_->Log(std::string("Freeing 2D Array Depth Map Index '") + std::to_string(Index) + std::string("'"), 4); + // Sanity Check if (Index > DepthMapTexturesAlreadyAllocated_.size() - 1) { + SystemUtils_->Logger_->Log(std::string("Cannot Free Invalid 2D Array Depth Map Index '") + std::to_string(Index) + std::string("', Index Out Of Range"), 9); return false; // Indicate Failure, Out Of Range } // DeAllocate From Array DepthMapTexturesAlreadyAllocated_[Index] = -1; + SystemUtils_->Logger_->Log(std::string("Deallocated 2D Array Depth Map Index '") + std::to_string(Index) + std::string("'"), 3); return true; } bool ERS_CLASS_DepthMaps::FreeDepthMapIndexCubemap(unsigned int Index) { + SystemUtils_->Logger_->Log(std::string("Freeing Cubemap Array Depth Map Index '") + std::to_string(Index) + std::string("'"), 4); + // Sanity Check if (Index > DepthMapTexturesCubemapAlreadyAllocated_.size() - 1) { + SystemUtils_->Logger_->Log(std::string("Cannot Free Invalid Cubemap Array Depth Map Index '") + std::to_string(Index) + std::string("', Index Out Of Range"), 9); return false; // Indicate Failure, Out Of Range } // DeAllocate From Array - DepthMapTexturesCubemapAlreadyAllocated_[Index] = -1; //ERS_STRUCT_CubemapFBOIndexes(); + DepthMapTexturesCubemapAlreadyAllocated_[Index] = -1; + SystemUtils_->Logger_->Log(std::string("Deallocated Cubemap Array Depth Map Index '") + std::to_string(Index) + std::string("'"), 3); return true; } @@ -338,127 +347,145 @@ ERS_STRUCT_DepthMap ERS_CLASS_DepthMaps::GenerateDepthMap2D(int Number, bool Log void ERS_CLASS_DepthMaps::UpdateDepthMap(ERS_STRUCT_DirectionalLight* Light, ERS_STRUCT_Shader* DepthShader) { - // Check Settings - CheckSettings(); + // Only Update If Instructed To Do SO + if (Light->DepthMap.ToBeUpdated) { - // Setup Variables - glm::mat4* LightSpaceMatrixArray = &Light->DepthMap.TransformationMatrix; - ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); - glm::mat4 ObjectProjection, ObjectView, ObjectSpace; - float NearPlane = 0.1f, FarPlane = 15.0f; + // Setup Variables + glm::mat4* LightSpaceMatrixArray = &Light->DepthMap.TransformationMatrix; + ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); + glm::mat4 ObjectProjection, ObjectView, ObjectSpace; + float NearPlane = 0.1f, FarPlane = 15.0f; - // Calculate Project, View, Space Matrices - ObjectProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, NearPlane, FarPlane); // ortho models directional light source + // Calculate Project, View, Space Matrices + ObjectProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, NearPlane, FarPlane); // ortho models directional light source - // Re-Do Rotation - glm::vec3 XYZRotation = ERS_FUNCTION_ConvertRotationToFrontVector(Light->Rot); + // Re-Do Rotation + glm::vec3 XYZRotation = ERS_FUNCTION_ConvertRotationToFrontVector(Light->Rot); - glm::vec3 Front = glm::normalize(XYZRotation); - ObjectView = glm::lookAt(Light->Pos, Light->Pos+Front, glm::vec3(0.0f, 1.0f, 0.0f)); // Pos+Front - ObjectSpace = ObjectProjection * ObjectView; + glm::vec3 Front = glm::normalize(XYZRotation); + ObjectView = glm::lookAt(Light->Pos, Light->Pos+Front, glm::vec3(0.0f, 1.0f, 0.0f)); // Pos+Front + ObjectSpace = ObjectProjection * ObjectView; - // Render With Depth Shader - DepthShader->MakeActive(); - DepthShader->SetMat4("LightSpaceMatrix", ObjectSpace); - *LightSpaceMatrixArray = ObjectSpace; + // Render With Depth Shader + DepthShader->MakeActive(); + DepthShader->SetMat4("LightSpaceMatrix", ObjectSpace); + *LightSpaceMatrixArray = ObjectSpace; - glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); - glBindFramebuffer(GL_FRAMEBUFFER, Light->DepthMap.FrameBufferObjectID); + glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); + glBindFramebuffer(GL_FRAMEBUFFER, Light->DepthMap.FrameBufferObjectID); - - glClear(GL_DEPTH_BUFFER_BIT); - glActiveTexture(GL_TEXTURE0); - Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); + + glClear(GL_DEPTH_BUFFER_BIT); + glActiveTexture(GL_TEXTURE0); + Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset After Updating + Light->DepthMap.ToBeUpdated = false; + + } } void ERS_CLASS_DepthMaps::UpdateDepthMap(ERS_STRUCT_PointLight* Light, ERS_STRUCT_Shader* DepthShader) { + // Only Update If Instructed To Do SO + if (Light->DepthMap.ToBeUpdated) { - // Setup Variables - ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); - float NearPlane, FarPlane; - NearPlane = 0.1f; - FarPlane = Light->MaxDistance; - - // Calculate Project, View, Space Matrices - float AspectRatio = DepthTextureArrayWidth_ / DepthTextureArrayHeight_; - glm::mat4 ShadowProjection = glm::perspective(glm::radians(90.0f), AspectRatio, NearPlane, FarPlane); // Perspective models regular light source - - std::vector ShadowTransforms; - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 1.0, 0.0, 0.0), glm::vec3(0.0,-1.0, 0.0))); - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0,-1.0, 0.0))); - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0))); - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0,-1.0, 0.0), glm::vec3(0.0, 0.0,-1.0))); - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 0.0, 1.0), glm::vec3(0.0,-1.0, 0.0))); - ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 0.0,-1.0), glm::vec3(0.0,-1.0, 0.0))); - + // Clear This Layer Of The Cubemap Array + for (unsigned int i = 0; i < 6; i++) { + glBindFramebuffer(GL_FRAMEBUFFER, PointLightClearFBO_); + glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, DepthTextureCubemapArrayID_, 0, Light->DepthMap.DepthMapTextureIndex*6 + i); + glClear(GL_DEPTH_BUFFER_BIT); + } + // Setup Variables + ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); + float NearPlane, FarPlane; + NearPlane = 0.1f; + FarPlane = Light->MaxDistance; - // Render All Sides - glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); + // Calculate Project, View, Space Matrices + float AspectRatio = DepthTextureArrayWidth_ / DepthTextureArrayHeight_; + glm::mat4 ShadowProjection = glm::perspective(glm::radians(90.0f), AspectRatio, NearPlane, FarPlane); // Perspective models regular light source + + std::vector ShadowTransforms; + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 1.0, 0.0, 0.0), glm::vec3(0.0,-1.0, 0.0))); + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0,-1.0, 0.0))); + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0))); + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0,-1.0, 0.0), glm::vec3(0.0, 0.0,-1.0))); + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 0.0, 1.0), glm::vec3(0.0,-1.0, 0.0))); + ShadowTransforms.push_back(ShadowProjection * glm::lookAt(Light->Pos, Light->Pos + glm::vec3( 0.0, 0.0,-1.0), glm::vec3(0.0,-1.0, 0.0))); + + + // Render All Sides + glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); + glBindFramebuffer(GL_FRAMEBUFFER, CubemapFBO_); + DepthShader->MakeActive(); + for (unsigned int i = 0; i < ShadowTransforms.size(); i++) { + DepthShader->SetMat4(std::string("ShadowMatrices[") + std::to_string(i) + std::string("]"), ShadowTransforms[i]); + } + DepthShader->SetVec3("LightPos", Light->Pos); + DepthShader->SetFloat("FarPlane", Light->MaxDistance); + DepthShader->SetInt("ShadowMapLayer", Light->DepthMap.DepthMapTextureIndex); + Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); - DepthShader->MakeActive(); + // Reset After Updating + Light->DepthMap.ToBeUpdated = false; - // Render With Depth Shader - for (unsigned int i = 0; i < ShadowTransforms.size(); i++) { - DepthShader->SetMat4(std::string("ShadowMatrices[") + std::to_string(i) + std::string("]"), ShadowTransforms[i]); } - DepthShader->SetVec3("LightPos", Light->Pos); - DepthShader->SetFloat("FarPlane", Light->MaxDistance); - DepthShader->SetInt("ShadowMapLayer", Light->DepthMap.DepthMapTextureIndex); - Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); - } void ERS_CLASS_DepthMaps::UpdateDepthMap(ERS_STRUCT_SpotLight* Light, ERS_STRUCT_Shader* DepthShader) { - // Check Settings - CheckSettings(); + // Only Update If Instructed To Do So + if (Light->DepthMap.ToBeUpdated) { - // Setup Variables - glm::mat4* LightSpaceMatrixArray = &Light->DepthMap.TransformationMatrix; - ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); - glm::mat4 ObjectProjection, ObjectView, ObjectSpace; - float NearPlane, FarPlane; - NearPlane = 0.1f; - FarPlane = Light->MaxDistance; + // Setup Variables + glm::mat4* LightSpaceMatrixArray = &Light->DepthMap.TransformationMatrix; + ERS_STRUCT_Scene* TargetScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); + glm::mat4 ObjectProjection, ObjectView, ObjectSpace; + float NearPlane, FarPlane; + NearPlane = 0.1f; + FarPlane = Light->MaxDistance; - // Calculate Project, View, Space Matrices - float AspectRatio = DepthTextureArrayWidth_ / DepthTextureArrayHeight_; - float FOV = glm::radians(130.0f);// * (0.01745329)); - ObjectProjection = glm::perspective(FOV, AspectRatio, NearPlane, FarPlane); // Perspective models regular light source - - // Re-Do Rotation - glm::vec3 XYZRotation = ERS_FUNCTION_ConvertRotationToFrontVector(Light->Rot); - glm::vec3 Front = glm::normalize(XYZRotation); - ObjectView = glm::lookAt(Light->Pos, Light->Pos+Front, glm::vec3(0.0f, 1.0f, 0.0f)); // Pos+Front - ObjectSpace = ObjectProjection * ObjectView; - - // Render With Depth Shader - DepthShader->MakeActive(); - DepthShader->SetMat4("LightSpaceMatrix", ObjectSpace); - *LightSpaceMatrixArray = ObjectSpace; - - glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); - glBindFramebuffer(GL_FRAMEBUFFER, Light->DepthMap.FrameBufferObjectID); - glClear(GL_DEPTH_BUFFER_BIT); - glActiveTexture(GL_TEXTURE0); - Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); + // Calculate Project, View, Space Matrices + float AspectRatio = DepthTextureArrayWidth_ / DepthTextureArrayHeight_; + float FOV = glm::radians(130.0f);// * (0.01745329)); + ObjectProjection = glm::perspective(FOV, AspectRatio, NearPlane, FarPlane); // Perspective models regular light source + + // Re-Do Rotation + glm::vec3 XYZRotation = ERS_FUNCTION_ConvertRotationToFrontVector(Light->Rot); + glm::vec3 Front = glm::normalize(XYZRotation); + ObjectView = glm::lookAt(Light->Pos, Light->Pos+Front, glm::vec3(0.0f, 1.0f, 0.0f)); // Pos+Front + ObjectSpace = ObjectProjection * ObjectView; + + // Render With Depth Shader + DepthShader->MakeActive(); + DepthShader->SetMat4("LightSpaceMatrix", ObjectSpace); + *LightSpaceMatrixArray = ObjectSpace; + + glViewport(0, 0, DepthTextureArrayWidth_, DepthTextureArrayHeight_); + glBindFramebuffer(GL_FRAMEBUFFER, Light->DepthMap.FrameBufferObjectID); + glClear(GL_DEPTH_BUFFER_BIT); + glActiveTexture(GL_TEXTURE0); + Renderer_->RenderSceneNoTextures(TargetScene, DepthShader); + + + // Reset After Updating + Light->DepthMap.ToBeUpdated = false; + + } } void ERS_CLASS_DepthMaps::UpdateDepthMaps(ERS_STRUCT_Shader* DepthShader, ERS_STRUCT_Shader* CubemapDepthShader) { - // Check Settings - CheckSettings(); - // Fix Offset (Peter Panning) glCullFace(GL_FRONT); @@ -471,13 +498,10 @@ void ERS_CLASS_DepthMaps::UpdateDepthMaps(ERS_STRUCT_Shader* DepthShader, ERS_S // Extract Struct ERS_STRUCT_DirectionalLight* Light = ActiveScene->DirectionalLights[i].get(); - // Check If Light Has DepthMap - if (!Light->DepthMap.Initialized) { - Light->DepthMap = GenerateDepthMap2D(); - } - // Render To Depth Map - UpdateDepthMap(Light, DepthShader); + if (Light->CastsShadows_) { + UpdateDepthMap(Light, DepthShader); + } } @@ -487,33 +511,23 @@ void ERS_CLASS_DepthMaps::UpdateDepthMaps(ERS_STRUCT_Shader* DepthShader, ERS_S // Extract Struct ERS_STRUCT_SpotLight* Light = ActiveScene->SpotLights[i].get(); - // Check If Light Has DepthMap - if (!Light->DepthMap.Initialized) { - Light->DepthMap = GenerateDepthMap2D(); - } - // Render To Depth Map - UpdateDepthMap(Light, DepthShader); + if (Light->CastsShadows_) { + UpdateDepthMap(Light, DepthShader); + } } // Handle Point Lights - glBindFramebuffer(GL_FRAMEBUFFER, CubemapFBO_); - glClear(GL_DEPTH_BUFFER_BIT); - for (unsigned int i = 0; i < ActiveScene->PointLights.size(); i++) { // Extract Struct ERS_STRUCT_PointLight* Light = ActiveScene->PointLights[i].get(); - // Check If Light Has DepthMap - if (!Light->DepthMap.Initialized) { - Light->DepthMap.DepthMapTextureIndex = AllocateDepthMapIndexCubemap(); - Light->DepthMap.Initialized = true; - } - // Render To Depth Map - UpdateDepthMap(Light, CubemapDepthShader); + if (Light->CastsShadows_) { + UpdateDepthMap(Light, CubemapDepthShader); + } } @@ -522,4 +536,5 @@ void ERS_CLASS_DepthMaps::UpdateDepthMaps(ERS_STRUCT_Shader* DepthShader, ERS_S // Return To Normal Culling glCullFace(GL_BACK); + } \ No newline at end of file diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.h index 4e22d2820f..04dd098f37 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.h +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_DepthMaps.h @@ -31,6 +31,8 @@ #include #include + + #include @@ -64,36 +66,13 @@ class ERS_CLASS_DepthMaps { unsigned int DepthMapAllocationChunkSize_ = 16; /** OpaqueMeshes; std::vector TransparentMeshes; - ERS_FUNCTION_MeshTransparencySort(&OpaqueMeshes, &TransparentMeshes, Scene); + ERS_FUNCTION_MeshTransparencySortNoTextures(&OpaqueMeshes, &TransparentMeshes, Scene); // Draw All Opaque Meshes for (unsigned long i = 0; i < OpaqueMeshes.size(); i++) { diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_MeshRenderer.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_MeshRenderer.h index 5da5dfda21..8da83f3c92 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_MeshRenderer.h +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_MeshRenderer.h @@ -29,6 +29,7 @@ #include #include +#include #include #include diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.cpp b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.cpp index cbbdd64115..72e6f8a866 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.cpp +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.cpp @@ -14,6 +14,7 @@ ERS_CLASS_ShadowMaps::ERS_CLASS_ShadowMaps(ERS_STRUCT_SystemUtils* SystemUtils, SystemUtils_->Logger_->Log("Initializing Shadow Map Subsystem", 5); ERS_CLASS_DepthMaps_ = std::make_unique(SystemUtils_, ProjectUtils_, Renderer_); + MersenneTwister_.seed(RandomSeed_); } @@ -23,14 +24,192 @@ ERS_CLASS_ShadowMaps::~ERS_CLASS_ShadowMaps() { } +void ERS_CLASS_ShadowMaps::DeallocateLightMaps() { -void ERS_CLASS_ShadowMaps::UpdateShadowMaps(ERS_STRUCT_Shader* DepthMapShader, ERS_STRUCT_Shader* CubemapDepthShader) { + // Iterate Over All Depth Maps, And Dellocate It + SystemUtils_->Logger_->Log("Deallocating All Depth Map Indices", 5); + ERS_STRUCT_Scene* ActiveScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); - // Update All Depth Maps - ERS_CLASS_DepthMaps_->UpdateDepthMaps(DepthMapShader, CubemapDepthShader); + for (unsigned int i = 0; i < ActiveScene->PointLights.size(); i++) { + + if (ActiveScene->PointLights[i]->DepthMap.Initialized) { + ERS_CLASS_DepthMaps_->FreeDepthMapIndexCubemap(ActiveScene->PointLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->PointLights[i]->DepthMap.Initialized = false; + } + + } + + for (unsigned int i = 0; i < ActiveScene->SpotLights.size(); i++) { + + if (ActiveScene->SpotLights[i]->DepthMap.Initialized) { + ERS_CLASS_DepthMaps_->FreeDepthMapIndex2D(ActiveScene->SpotLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->SpotLights[i]->DepthMap.Initialized = false; + } + + } + + for (unsigned int i = 0; i < ActiveScene->DirectionalLights.size(); i++) { + + if (ActiveScene->DirectionalLights[i]->DepthMap.Initialized) { + ERS_CLASS_DepthMaps_->FreeDepthMapIndex2D(ActiveScene->DirectionalLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->DirectionalLights[i]->DepthMap.Initialized = false; + } + + } + SystemUtils_->Logger_->Log("Finished Dallocating All Depth Map Indices", 4); + +} + +void ERS_CLASS_ShadowMaps::GetDepthMaps(std::vector* DepthMaps, std::vector* LightPositions) { + + ERS_STRUCT_Scene* ActiveScene = ProjectUtils_->SceneManager_->Scenes_[ProjectUtils_->SceneManager_->ActiveScene_].get(); + for (unsigned int i = 0; i < ActiveScene->PointLights.size(); i++) { + if (ActiveScene->PointLights[i]->CastsShadows_) { + + // Check If Light Has DepthMap + if (!ActiveScene->PointLights[i]->DepthMap.Initialized) { + ActiveScene->PointLights[i]->DepthMap.DepthMapTextureIndex = ERS_CLASS_DepthMaps_->AllocateDepthMapIndexCubemap(); + ActiveScene->PointLights[i]->DepthMap.Initialized = true; + } + + + + DepthMaps->push_back(&ActiveScene->PointLights[i]->DepthMap); + LightPositions->push_back(ActiveScene->PointLights[i]->Pos); + + } else if (ActiveScene->PointLights[i]->DepthMap.Initialized) { + + // Free The Light Index If Not Enabled + ERS_CLASS_DepthMaps_->FreeDepthMapIndexCubemap(ActiveScene->PointLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->PointLights[i]->DepthMap.Initialized = false; + } + } + for (unsigned int i = 0; i < ActiveScene->SpotLights.size(); i++) { + if (ActiveScene->SpotLights[i]->CastsShadows_) { + + // Check If Light Has DepthMap + if (!ActiveScene->SpotLights[i]->DepthMap.Initialized) { + ActiveScene->SpotLights[i]->DepthMap = ERS_CLASS_DepthMaps_->GenerateDepthMap2D(); + } + + DepthMaps->push_back(&ActiveScene->SpotLights[i]->DepthMap); + LightPositions->push_back(ActiveScene->SpotLights[i]->Pos); + + } else if (ActiveScene->SpotLights[i]->DepthMap.Initialized) { + + // Free The Light Index If Not Enabled + ERS_CLASS_DepthMaps_->FreeDepthMapIndex2D(ActiveScene->SpotLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->SpotLights[i]->DepthMap.Initialized = false; + } + } + + // All Directional Lights Will Be Updated + for (unsigned int i = 0; i < ActiveScene->DirectionalLights.size(); i++) { + if (ActiveScene->DirectionalLights[i]->CastsShadows_) { + + // Check If Light Has DepthMap + if (!ActiveScene->DirectionalLights[i]->DepthMap.Initialized) { + ActiveScene->DirectionalLights[i]->DepthMap = ERS_CLASS_DepthMaps_->GenerateDepthMap2D(); + } + + ActiveScene->DirectionalLights[i]->DepthMap.ToBeUpdated = true; + } else if (ActiveScene->DirectionalLights[i]->DepthMap.Initialized) { + + // Free The Light Index If Not Enabled + ERS_CLASS_DepthMaps_->FreeDepthMapIndex2D(ActiveScene->DirectionalLights[i]->DepthMap.DepthMapTextureIndex); + ActiveScene->DirectionalLights[i]->DepthMap.Initialized = false; + } + + } + +} - // Provide Depth Map Textures - +void ERS_CLASS_ShadowMaps::PrioritizeDepthMaps(std::vector DepthMaps, std::vector LightPositions, glm::vec3 CameraPosition) { + + + ERS::Renderer::ShadowUpdateMode UpdateMode = SystemUtils_->RendererSettings_->ShadowUpdateMode_; + + + // Skip Handling An Update If No Lights Are To Be Updated Here + if (DepthMaps.size() > 1) { + + // Tell The Depth Map Update System Which Depth Maps To Update + if (UpdateMode == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISABLED) { + // Do Nothing As All Updates Are Disabled + } else if (UpdateMode == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_ALL) { + + for (unsigned int i = 0; i < DepthMaps.size(); i++) { + + DepthMaps[i]->ToBeUpdated = true; + + } + } else if (UpdateMode == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_CONSECUTIVE) { + for (int i = 0; i < SystemUtils_->RendererSettings_->MaxShadowUpdatesPerFrame_; i++) { + + // Calculate The Current index, Wrap At End Of List Size + LastUpdateIndex_++; + if (LastUpdateIndex_ > DepthMaps.size() - 1) { + LastUpdateIndex_ = 0; + } + + DepthMaps[LastUpdateIndex_]->ToBeUpdated = true; + + } + } else if (UpdateMode == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_RANDOM) { + + // Randomly Update The Light, Note: Updates Are Guarenteed To Be Less Than Max But Not Equal To That + for (int i = 0; i < SystemUtils_->RendererSettings_->MaxShadowUpdatesPerFrame_; i++) { + int UpdateIndex = RandomNumberGenerator_(MersenneTwister_) % (DepthMaps.size()-1); + DepthMaps[UpdateIndex]->ToBeUpdated = true; + } + + } else if (UpdateMode == ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED) { + + // Create Sorted List Of Light Indexes Based On Distance + std::map LightDistances; + for (unsigned int i = 0; i < DepthMaps.size(); i++) { + float Distance = glm::distance(CameraPosition, LightPositions[i]); + LightDistances.insert(std::make_pair(Distance, i)); + } + + std::vector SortedLightDistances; + for (auto const& Entry : LightDistances) { + SortedLightDistances.push_back(Entry.second); + } + + + // Mark Lights To Be Updated + for (int i = 0; i < SystemUtils_->RendererSettings_->MaxShadowUpdatesPerFrame_; i++) { + unsigned int DepthMapIndex = SortedLightDistances[i]; + if ((signed long)RandomNumberGenerator_(MersenneTwister_) % (signed long)(DepthMaps.size()-1) == (signed long)i) { + DepthMapIndex = RandomNumberGenerator_(MersenneTwister_) % (DepthMaps.size()-1); + } + DepthMaps[DepthMapIndex]->ToBeUpdated = true; + } + + + } + + } else if (DepthMaps.size() == 1) { // Handle Edge Case Where One Light Breaks The Random Number Generator + DepthMaps[0]->ToBeUpdated = true; + } + + +} + +void ERS_CLASS_ShadowMaps::UpdateShadowMaps(ERS_STRUCT_Shader* DepthMapShader, ERS_STRUCT_Shader* CubemapDepthShader, glm::vec3 CameraPosition) { + + // Get Updated Info From Renderer Settings + ERS_CLASS_DepthMaps_->CheckSettings(); + + // Handle Updating Depth Maps + std::vector DepthMaps; + std::vector LightPositions; + GetDepthMaps(&DepthMaps, &LightPositions); + PrioritizeDepthMaps(DepthMaps, LightPositions, CameraPosition); + + // Update All Depth Maps + ERS_CLASS_DepthMaps_->UpdateDepthMaps(DepthMapShader, CubemapDepthShader); } \ No newline at end of file diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.h index 16afd5586f..5960b70fa5 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.h +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_ShadowMaps.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include // Third-Party Libraries (BG convention: use <> instead of "") #include @@ -30,6 +32,8 @@ #include #include +#include +#include /** @@ -46,9 +50,32 @@ class ERS_CLASS_ShadowMaps { ERS_CLASS_MeshRenderer* Renderer_; /** RandomNumberGenerator_; /*** DepthMaps, std::vector* LightPositions); + + /** + * @brief Determines which depth maps should be updated, and also deallocates those on lights that are no longer being used. + * + * @param DepthMaps + * @param LightPositions + */ + void PrioritizeDepthMaps(std::vector DepthMaps, std::vector LightPositions, glm::vec3 CameraPosition); + + public: std::unique_ptr ERS_CLASS_DepthMaps_; /**UpdateShadowMaps(DepthMapShader_, CubemapDepthShader_); - + if (Viewports_.size() > 0) { + ShadowMaps_->UpdateShadowMaps(DepthMapShader_, CubemapDepthShader_, Viewports_[0]->Camera->Position_); + } // Setup Vars glEnable(GL_DEPTH_TEST); @@ -677,6 +678,8 @@ void ERS_CLASS_VisualRenderer::UpdateShader(int ShaderIndex, float DeltaTime, in ActiveShader->SetFloat((UniformName + std::string(".MaxDistance")).c_str(), ActiveScene->DirectionalLights[i]->MaxDistance); + ActiveShader->SetBool((UniformName + std::string(".CastsShadows")).c_str(), ActiveScene->DirectionalLights[i]->CastsShadows_); + ActiveShader->SetInt((UniformName + std::string(".DepthMapIndex")).c_str(), ActiveScene->DirectionalLights[i]->DepthMap.DepthMapTextureIndex); ActiveShader->SetMat4((UniformName + std::string(".LightSpaceMatrix")).c_str(), ActiveScene->DirectionalLights[i]->DepthMap.TransformationMatrix); @@ -694,7 +697,8 @@ void ERS_CLASS_VisualRenderer::UpdateShader(int ShaderIndex, float DeltaTime, in ActiveShader->SetVec3((UniformName + std::string(".Color")).c_str(), ActiveScene->PointLights[i]->Color); ActiveShader->SetFloat((UniformName + std::string(".MaxDistance")).c_str(), ActiveScene->PointLights[i]->MaxDistance); - + + ActiveShader->SetBool((UniformName + std::string(".CastsShadows")).c_str(), ActiveScene->PointLights[i]->CastsShadows_); ActiveShader->SetInt((UniformName + std::string(".DepthCubemapIndex")).c_str(), ActiveScene->PointLights[i]->DepthMap.DepthMapTextureIndex); @@ -743,6 +747,8 @@ void ERS_CLASS_VisualRenderer::UpdateShader(int ShaderIndex, float DeltaTime, in ActiveShader->SetFloat((UniformName + std::string(".MaxDistance")).c_str(), ActiveScene->SpotLights[i]->MaxDistance); + ActiveShader->SetBool((UniformName + std::string(".CastsShadows")).c_str(), ActiveScene->SpotLights[i]->CastsShadows_); + ActiveShader->SetInt((UniformName + std::string(".DepthMapIndex")).c_str(), ActiveScene->SpotLights[i]->DepthMap.DepthMapTextureIndex); ActiveShader->SetMat4((UniformName + std::string(".LightSpaceMatrix")).c_str(), ActiveScene->SpotLights[i]->DepthMap.TransformationMatrix); @@ -750,6 +756,22 @@ void ERS_CLASS_VisualRenderer::UpdateShader(int ShaderIndex, float DeltaTime, in } + // Set Shadow Filter Info + int ShadowFilterType = 0; + ERS::Renderer::ShadowFilteringType ShadowFilterEnum = SystemUtils_->RendererSettings_->ShadowFilteringType_; + if (ShadowFilterEnum == ERS::Renderer::ERS_SHADOW_FILTERING_DISABLED) { + ShadowFilterType = 0; + } else if (ShadowFilterEnum == ERS::Renderer::ERS_SHADOW_FILTERING_PCF) { + ShadowFilterType = 1; + } else if (ShadowFilterEnum == ERS::Renderer::ERS_SHADOW_FILTERING_POISSON_SAMPLING) { + ShadowFilterType = 2; + } else if (ShadowFilterEnum == ERS::Renderer::ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING) { + ShadowFilterType = 3; + } + ActiveShader->SetInt("ShadowFilterType_", ShadowFilterType); + ActiveShader->SetInt("ShadowFilterKernelSize_", SystemUtils_->RendererSettings_->ShadowFilterKernelSize_); + + ActiveShader->SetFloat("Shinyness", 32.0f); diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_VisualRenderer.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_VisualRenderer.h index 6f7d66b9aa..3cbffe4bf0 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_VisualRenderer.h +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_CLASS_VisualRenderer.h @@ -48,6 +48,8 @@ #include #include +#include + /** * @brief Handles viewport creation/deletion/rendering/updating. * diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.cpp b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.cpp index b6eb2205e1..4f25bfd0ea 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.cpp +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.cpp @@ -103,9 +103,15 @@ void ERS_FUNCTION_DrawMesh(ERS_STRUCT_Mesh* Mesh, ERS_STRUCT_OpenGLDefaults* Ope Shader->SetBool("HasMetalness", HasMetalness); Shader->SetBool("HasNormals", HasNormals); Shader->SetBool("HasShininess", HasShininess); + + // Shadow Control Uniforms + Shader->SetBool("CastDynamicShadows_", *Mesh->CastDynamicShadows_); + Shader->SetBool("CastStaticShadows_", *Mesh->CastStaticShadows_); + Shader->SetBool("ReceiveShadows_", *Mesh->ReceiveShadows_); + // Draw Mesh glBindVertexArray(Mesh->VAO); glDrawElements(GL_TRIANGLES, Mesh->NumberIndices, GL_UNSIGNED_INT, 0); diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.h index c823265541..f582fe1350 100644 --- a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.h +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_DrawMesh.h @@ -21,6 +21,7 @@ + /** * @brief Draws the mesh passed in. * diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.cpp b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.cpp new file mode 100644 index 0000000000..da42b30f7f --- /dev/null +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.cpp @@ -0,0 +1,32 @@ +//======================================================================// +// This file is part of the BrainGenix-ERS Environment Rendering System // +//======================================================================// + +#include + + +void ERS_FUNCTION_MeshTransparencySortNoTextures(std::vector* OpaqueMeshes, std::vector* TransparentMeshes, ERS_STRUCT_Scene* Scene) { + + + for (unsigned long i = 0; i < Scene->Models.size(); i++) { + + ERS_STRUCT_Model *Model = Scene->Models[i].get(); + glm::mat4 ModelMatrix = Model->GetMat4(); + if (Model->FullyReady && Model->Enabled && Model->CastDynamicShadows_) { + for (unsigned int i = 0; i < Model->Meshes.size(); i++) { + + ERS_STRUCT_Mesh* Mesh = &Model->Meshes[i]; + Mesh->ModelMatrix = ModelMatrix; + if (Mesh->HasTransparency_) { + TransparentMeshes->push_back(Mesh); + } else { + OpaqueMeshes->push_back(Mesh); + } + + } + } + + } + + +} \ No newline at end of file diff --git a/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.h b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.h new file mode 100644 index 0000000000..906027983c --- /dev/null +++ b/Source/Core/Renderer/ERS_CLASS_VisualRenderer/ERS_FUNCTION_MeshTransparencySortNoTextures.h @@ -0,0 +1,28 @@ +//======================================================================// +// This file is part of the BrainGenix-ERS Environment Rendering System // +//======================================================================// + +#pragma once + + +// Standard Libraries (BG convention: use <> instead of "") +#include +#include + +// Third-Party Libraries (BG convention: use <> instead of "") + +// Internal Libraries (BG convention: use <> instead of "") +#include + +#include +#include + + +/** + * @brief Sorts the meshes in the given scene into the opaque and transparent meshes vectors. Also updates the "model" mat4 in the mesh. + * + * @param OpaqueMeshes + * @param TransparentMeshes + * @param Scene + */ +void ERS_FUNCTION_MeshTransparencySortNoTextures(std::vector* OpaqueMeshes, std::vector* TransparentMeshes, ERS_STRUCT_Scene* Scene); \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_DepthMap/ERS_STRUCT_DepthMap.h b/Source/Core/Structures/ERS_STRUCT_DepthMap/ERS_STRUCT_DepthMap.h index c1267f52a3..c69dc22188 100644 --- a/Source/Core/Structures/ERS_STRUCT_DepthMap/ERS_STRUCT_DepthMap.h +++ b/Source/Core/Structures/ERS_STRUCT_DepthMap/ERS_STRUCT_DepthMap.h @@ -30,5 +30,6 @@ struct ERS_STRUCT_DepthMap { glm::mat4 TransformationMatrix; /** TextureNames; /** \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowFilteringType.h b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowFilteringType.h new file mode 100644 index 0000000000..da38374398 --- /dev/null +++ b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowFilteringType.h @@ -0,0 +1,30 @@ +//======================================================================// +// This file is part of the BrainGenix-ERS Environment Rendering System // +//======================================================================// + +#pragma once + +// Standard Libraries (BG convention: use <> instead of "") +#include + +// Third-Party Libraries (BG convention: use <> instead of "") + +// Internal Libraries (BG convention: use <> instead of "") + + +namespace ERS { + + namespace Renderer { + + enum ShadowFilteringType { + + ERS_SHADOW_FILTERING_DISABLED, + ERS_SHADOW_FILTERING_PCF, + ERS_SHADOW_FILTERING_POISSON_SAMPLING, + ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING + + }; + + } + +} \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.cpp b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.cpp new file mode 100644 index 0000000000..32270f38ef --- /dev/null +++ b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.cpp @@ -0,0 +1,5 @@ +//======================================================================// +// This file is part of the BrainGenix-ERS Environment Rendering System // +//======================================================================// + +#include \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.h b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.h new file mode 100644 index 0000000000..c306f80446 --- /dev/null +++ b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_ENUM_ShadowUpdateMode.h @@ -0,0 +1,31 @@ +//======================================================================// +// This file is part of the BrainGenix-ERS Environment Rendering System // +//======================================================================// + +#pragma once + +// Standard Libraries (BG convention: use <> instead of "") +#include + +// Third-Party Libraries (BG convention: use <> instead of "") + +// Internal Libraries (BG convention: use <> instead of "") + + +namespace ERS { + + namespace Renderer { + + enum ShadowUpdateMode { + + ERS_SHADOW_UPDATE_MODE_DISABLED, + ERS_SHADOW_UPDATE_MODE_RANDOM, + ERS_SHADOW_UPDATE_MODE_CONSECUTIVE, + ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED, + ERS_SHADOW_UPDATE_MODE_ALL + + }; + + } + +} \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_STRUCT_RendererSettings.h b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_STRUCT_RendererSettings.h index d5cd22191b..7470012b55 100644 --- a/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_STRUCT_RendererSettings.h +++ b/Source/Core/Structures/ERS_STRUCT_RendererSettings/ERS_STRUCT_RendererSettings.h @@ -13,7 +13,8 @@ // Third-Party Libraries (BG convention: use <> instead of "") // Internal Libraries (BG convention: use <> instead of "") - +#include +#include /** @@ -26,8 +27,10 @@ struct ERS_STRUCT_RendererSettings { int ShadowMapX_ = 2048; int ShadowMapY_ = 2048; - - // Indicate If Settings Have Changed - bool HaveSettingsChanged_ = false; + // Set Shadow Update Settings + ERS::Renderer::ShadowFilteringType ShadowFilteringType_ = ERS::Renderer::ERS_SHADOW_FILTERING_STRATIFIED_POISSON_SAMPLING; + ERS::Renderer::ShadowUpdateMode ShadowUpdateMode_ = ERS::Renderer::ERS_SHADOW_UPDATE_MODE_DISTANCE_PRIORITIZED; + int MaxShadowUpdatesPerFrame_ = 5; + int ShadowFilterKernelSize_ = 1; }; \ No newline at end of file diff --git a/Source/Core/Writers/ERS_SceneWriter/ERS_SceneWriter.cpp b/Source/Core/Writers/ERS_SceneWriter/ERS_SceneWriter.cpp index d71da83906..5f02295f88 100644 --- a/Source/Core/Writers/ERS_SceneWriter/ERS_SceneWriter.cpp +++ b/Source/Core/Writers/ERS_SceneWriter/ERS_SceneWriter.cpp @@ -84,6 +84,11 @@ std::string SceneWriter::ProcessScene(ERS_STRUCT_Scene* InputScene) { Output << YAML::Key << "FlipTextures" << YAML::Value << InputScene->Models[i]->FlipTextures; + Output << YAML::Key << "CastDynamicShadows" << YAML::Value << InputScene->Models[i]->CastDynamicShadows_; + Output << YAML::Key << "CastStaticShadows" << YAML::Value << InputScene->Models[i]->CastStaticShadows_; + Output << YAML::Key << "ReceiveShadows" << YAML::Value << InputScene->Models[i]->ReceiveShadows_; + + Output<DirectionalLights[i]->Intensity; Output << YAML::Key << "MaxDistance" << YAML::Value << InputScene->DirectionalLights[i]->MaxDistance; + Output << YAML::Key << "CastShadows" << YAML::Value << InputScene->DirectionalLights[i]->CastsShadows_; + Output<PointLights[i]->Intensity; Output << YAML::Key << "MaxDistance" << YAML::Value << InputScene->PointLights[i]->MaxDistance; + Output << YAML::Key << "CastShadows" << YAML::Value << InputScene->PointLights[i]->CastsShadows_; + Output<SpotLights[i]->Rolloff; + Output << YAML::Key << "CastShadows" << YAML::Value << InputScene->SpotLights[i]->CastsShadows_; + + + Output<SpotLights[i]->AttachedScriptIndexes_.size(); x++) { diff --git a/Source/EditorAssets/Projects/DefaultProject/10040.ERS b/Source/EditorAssets/Projects/DefaultProject/10040.ERS index cf0e79dec9..a7604b2c1f 100644 --- a/Source/EditorAssets/Projects/DefaultProject/10040.ERS +++ b/Source/EditorAssets/Projects/DefaultProject/10040.ERS @@ -16,6 +16,7 @@ out VS_OUT { vec3 TangentViewPos; vec3 TangentFragPos; vec3 Normal; // Used when no normal map is available; + //vec4 FragPosLightSpace; } Object; @@ -68,3 +69,9 @@ void main() + + + + + + diff --git a/Source/EditorAssets/Projects/DefaultProject/10041.ERS b/Source/EditorAssets/Projects/DefaultProject/10041.ERS index 48d2ec1a5c..ad4ae25470 100644 --- a/Source/EditorAssets/Projects/DefaultProject/10041.ERS +++ b/Source/EditorAssets/Projects/DefaultProject/10041.ERS @@ -12,6 +12,7 @@ in VS_OUT { vec3 TangentViewPos; vec3 TangentFragPos; vec3 Normal; // Used when normal texture not present + //vec4 FragPosLightSpace; } Object; @@ -26,6 +27,8 @@ struct STRUCT_DirectionalLight { float MaxDistance; int DepthMapIndex; mat4 LightSpaceMatrix; + + bool CastsShadows; }; @@ -42,6 +45,8 @@ struct STRUCT_PointLight { float MaxDistance; int DepthCubemapIndex; + + bool CastsShadows; }; @@ -64,6 +69,8 @@ struct STRUCT_SpotLight { int DepthMapIndex; mat4 LightSpaceMatrix; + + bool CastsShadows; }; @@ -112,13 +119,18 @@ uniform bool HasNormals; uniform bool HasShininess; +// Get Shadow Configuration Information +uniform bool ReceiveShadows_; +uniform int ShadowFilterType_; +uniform int ShadowFilterKernelSize_; + // Get Lighting Info uniform int NumberDirectionalLights; uniform int NumberPointLights; uniform int NumberSpotLights; uniform STRUCT_DirectionalLight DirectionalLights[2]; uniform STRUCT_PointLight PointLights[42]; -uniform STRUCT_SpotLight SpotLights[64]; +uniform STRUCT_SpotLight SpotLights[56]; // Gamma Correction Info uniform bool GammaCorrectionEnabled_; @@ -129,82 +141,253 @@ uniform float Gamma_; const float PI = 3.14159265358979; vec2 PoissonDisk[16] = vec2[]( - vec2( -0.94201624, -0.39906216 ), - vec2( 0.94558609, -0.76890725 ), - vec2( -0.094184101, -0.92938870 ), - vec2( 0.34495938, 0.29387760 ), - vec2( -0.91588581, 0.45771432 ), - vec2( -0.81544232, -0.87912464 ), - vec2( -0.38277543, 0.27676845 ), - vec2( 0.97484398, 0.75648379 ), - vec2( 0.44323325, -0.97511554 ), - vec2( 0.53742981, -0.47373420 ), - vec2( -0.26496911, -0.41893023 ), - vec2( 0.79197514, 0.19090188 ), - vec2( -0.24188840, 0.99706507 ), - vec2( -0.81409955, 0.91437590 ), - vec2( 0.19984126, 0.78641367 ), - vec2( 0.14383161, -0.14100790 ) +vec2( -0.94201624, -0.39906216 ), +vec2( 0.94558609, -0.76890725 ), +vec2( -0.094184101, -0.92938870 ), +vec2( 0.34495938, 0.29387760 ), +vec2( -0.91588581, 0.45771432 ), +vec2( -0.81544232, -0.87912464 ), +vec2( -0.38277543, 0.27676845 ), +vec2( 0.97484398, 0.75648379 ), +vec2( 0.44323325, -0.97511554 ), +vec2( 0.53742981, -0.47373420 ), +vec2( -0.26496911, -0.41893023 ), +vec2( 0.79197514, 0.19090188 ), +vec2( -0.24188840, 0.99706507 ), +vec2( -0.81409955, 0.91437590 ), +vec2( 0.19984126, 0.78641367 ), +vec2( 0.14383161, -0.14100790 ) ); +vec3 Poisson3D[16] = vec3[] ( +vec3(0.7439873218536399, -0.541186283808202, 0.17664264608175007), +vec3(-0.275775456801057, -0.32272001542150996, 0.68133261147887), +vec3(0.44897621078416994, -0.467917730100453, -0.659653108566999), +vec3(-0.847784673329443, 0.028283810708670032, -0.400656977668405), +vec3(-0.727825771085918, -0.283869738690555, 0.08675202075392008), +vec3(-0.452855029609054, 0.66060589626431, 0.7711005629971599), +vec3(0.61847387859598, -0.33074145298451196, 0.51381932664663), +vec3(0.35371939232573, 0.3825031747110199, -0.18291005725040999), +vec3(0.08679201826453009, 0.61422011069953, -0.5682788607664411), +vec3(-0.733357671182603, 0.78749090107158, 0.42277105059474995), +vec3(0.58986698603258, -0.422245749272406, 0.42315440950914995), +vec3(-0.081056734547019, -0.26176304789259996, 0.33600588003173004), +vec3(-0.158656360581517, -0.436631633434445, 0.09938938915729989), +vec3(-0.534419173840433, 0.81530744861811, 0.26251380564645), +vec3(0.7347787003964199, -0.17376213055103995, -0.05371918901801098), +vec3(0.59472335595638, 0.43984056729822996, -0.564682560041547) +); + +vec3 SampleOffsetDirections[20] = vec3[] +( + vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), + vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), + vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), + vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1), + vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1) +); float random(vec3 seed, int i){ - vec4 seed4 = vec4(seed,i); - float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673)); - return fract(sin(dot_product) * 43758.5453); + vec4 seed4 = vec4(seed,i); + float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673)); + return fract(sin(dot_product) * 43758.5453); } -float ShadowPCF(float Bias, vec3 ProjCoords, int Index, float CurrentDepth, int SampleSize) { +float PCFSampler(float Bias, vec3 ProjCoords, int Index, float CurrentDepth, int SampleSize) { float shadow = 0.0; - vec2 texelSize = 1.0 / textureSize(DepthMapArray, 0).xy; - for(int x = -SampleSize; x <= SampleSize; ++x) - { - for(int y = -SampleSize; y <= SampleSize; ++y) - { + vec2 texelSize = 1.0 / textureSize(DepthMapArray, 0).xy; + for(int x = -SampleSize; x <= SampleSize; ++x) + { + for(int y = -SampleSize; y <= SampleSize; ++y) + { vec2 TexCoords2D = ProjCoords.xy + (vec2(x, y) * texelSize); - float pcfDepth = texture(DepthMapArray, vec3(TexCoords2D, Index)).r; - shadow += CurrentDepth - Bias > pcfDepth ? 1.0 : 0.0; - } - } - shadow /= (SampleSize*2)*(SampleSize*2); + float pcfDepth = texture(DepthMapArray, vec3(TexCoords2D, Index)).r; + shadow += CurrentDepth - Bias > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (SampleSize*2)*(SampleSize*2); + + return shadow; + +} + +float PCFSamplerCubemap(float BiasedCurrentDepth, vec3 TexCoords3D, int Index, float ViewDistance, int SampleSize) { + + float shadow = 0.0; + + int samples = SampleSize*SampleSize; + float diskRadius = 0.01f;//(1.0 + (viewDistance / far_plane)) / 25.0; + for(int i = 0; i < samples; ++i) + { + float closestDepth = texture(DepthMapCubeArray, vec4(TexCoords3D + SampleOffsetDirections[i] * diskRadius, Index)).r; + closestDepth *= ViewDistance; // undo mapping [0;1] + if(BiasedCurrentDepth > closestDepth) + shadow += 1.0; + } + shadow /= float(samples); + + return shadow; +} + - return shadow; +float PoissonSampler(float Bias, vec3 ProjCoords, int Index, float CurrentDepth, int SampleSize) { + + float shadow = 0.0f; + vec2 texelSize = 1.0f / textureSize(DepthMapArray, 0).xy; + + for(int x = -SampleSize; x <= SampleSize; ++x) + { + for(int y = -SampleSize; y <= SampleSize; ++y) + { + vec2 TexCoords2D = ProjCoords.xy + (vec2(x, y) * texelSize); + int index = int(x*y)%16; + float pcfDepth = texture(DepthMapArray, vec3(TexCoords2D + PoissonDisk[index]/700.0f, Index)).r; + shadow += CurrentDepth - Bias > pcfDepth ? 1.0f : 0.0f; + } + } + shadow /= (SampleSize*2)*(SampleSize*2); + return shadow; } +float PoissonSamplerCube(float BiasedCurrentDepth, vec3 TexCoords3D, int Index, float ViewDistance, int SampleSize) { + + float shadow = 0.0; + + int samples = SampleSize*SampleSize; + + + for(int i = 0; i < samples; ++i) + { + + vec3 PoissonOffset = vec3(Poisson3D[i%16]/150.0f); + float closestDepth = texture(DepthMapCubeArray, vec4(TexCoords3D + PoissonOffset, Index)).r; + closestDepth *= ViewDistance; // undo mapping [0;1] + if(BiasedCurrentDepth > closestDepth) + shadow += 1.0; + } + shadow /= float(samples); + + + return shadow; + +} -float ShadowPCFRandom(float Bias, vec3 ProjCoords, int Index, float CurrentDepth, int SampleSize) { +float StratifiedPoissonSampler(float Bias, vec3 ProjCoords, int Index, float CurrentDepth, int SampleSize) { float shadow = 0.0f; - vec2 texelSize = 1.0f / textureSize(DepthMapArray, 0).xy; + vec2 texelSize = 1.0f / textureSize(DepthMapArray, 0).xy; - for(int x = -SampleSize; x <= SampleSize; ++x) - { - for(int y = -SampleSize; y <= SampleSize; ++y) - { + for(int x = -SampleSize; x <= SampleSize; ++x) + { + for(int y = -SampleSize; y <= SampleSize; ++y) + { + vec2 TexCoords2D = ProjCoords.xy + (vec2(x, y) * texelSize); int index = int(16.0f*random(floor(gl_FragCoord.yxz*1000.0f), x*y))%16; - float pcfDepth = texture(DepthMapArray, vec3(TexCoords2D + PoissonDisk[index]/700.0f, Index)).r; - //pcfDepth = texture(DepthMapArray, vec3(TexCoords2D, Index)).r; - shadow += CurrentDepth - Bias > pcfDepth ? 1.0f : 0.0f; - - - - } - } - shadow /= (SampleSize*2)*(SampleSize*2); - - - return shadow; + float pcfDepth = texture(DepthMapArray, vec3(TexCoords2D + PoissonDisk[index]/700.0f, Index)).r; + //pcfDepth = texture(DepthMapArray, vec3(TexCoords2D, Index)).r; + shadow += CurrentDepth - Bias > pcfDepth ? 1.0f : 0.0f; + } + } + shadow /= (SampleSize*2)*(SampleSize*2); + return shadow; } +float StratifiedPoissonSamplerCube(float BiasedCurrentDepth, vec3 TexCoords3D, int Index, float ViewDistance, int SampleSize) { + + float shadow = 0.0; + + int samples = SampleSize*SampleSize; + for(int i = 0; i < samples; ++i) + { + int PoissonIndex = int(16.0f*random(floor(gl_FragCoord.yxz*1000.0f), int(i)))%16; + vec3 PoissonOffset = vec3(Poisson3D[PoissonIndex]/150.0f); + float closestDepth = texture(DepthMapCubeArray, vec4(TexCoords3D + PoissonOffset, Index)).r; + closestDepth *= ViewDistance; // undo mapping [0;1] + if(BiasedCurrentDepth > closestDepth) + shadow += 1.0; + } + shadow /= float(samples); + + + return shadow; + + +} + + +float ShadowCalculation(STRUCT_PointLight Light) +{ + + // If Shadows Are Not Enabled, Exit Early + if (!ReceiveShadows_ || !Light.CastsShadows) { + return 1.0f; + } + + // get vector between fragment position and light position + vec3 fragToLight = Object.FragPos - Light.Position; + // ise the fragment to light vector to sample from the depth map + float closestDepth = texture(DepthMapCubeArray, vec4(fragToLight, Light.DepthCubemapIndex)).r; + // it is currently in linear range between [0,1], let's re-transform it back to original depth value + closestDepth *= Light.MaxDistance; + // now get current linear depth as the length between the fragment and light position + float currentDepth = length(fragToLight); + // test for shadows + + // Generate Shadow Map Bias + int TextureSize = textureSize(DepthMapCubeArray, 0).x; + float BiasMax = 0.005f; + if (TextureSize <= 512) { + BiasMax = 0.075; + } else if (TextureSize <= 1024) { + BiasMax = 0.05; + } else if (TextureSize <= 2048) { + BiasMax = 0.03; + } else if (TextureSize <= 4096) { + BiasMax = 0.02; + } else if (TextureSize <= 8192) { + BiasMax = 0.015; + } else if (TextureSize <= 16384) { + BiasMax = 0.01; + } + + float Bias = max(0.00 * (1.0 - dot(Object.Normal, normalize(fragToLight))), BiasMax); + + + // Select Correct Filter Based On Selection Uniform + float Shadow; + if (ShadowFilterType_ == 0) { // No Filtering + Shadow = currentDepth - Bias > closestDepth ? 1.0 : 0.0; + } else if (ShadowFilterType_ == 1) { // PCF Filtering + Shadow = PCFSamplerCubemap(currentDepth-Bias, fragToLight, Light.DepthCubemapIndex, Light.MaxDistance, ShadowFilterKernelSize_); + } else if (ShadowFilterType_ == 2) { // Poisson Filtering + Shadow = PoissonSamplerCube(currentDepth-Bias, fragToLight, Light.DepthCubemapIndex, Light.MaxDistance, ShadowFilterKernelSize_); + } else if (ShadowFilterType_ == 3) { + Shadow = StratifiedPoissonSamplerCube(currentDepth-Bias, fragToLight, Light.DepthCubemapIndex, Light.MaxDistance, ShadowFilterKernelSize_); + } else { + return 0.0f; // Return Failure, All Black) + } + + // display closestDepth as debug (to visualize depth cubemap) + // FragColor = vec4(vec3(closestDepth / Light.MaxDistance), 1.0); + + return 1.0f - Shadow; +} float ShadowCalculation(mat4 LightSpaceMatrix, vec3 LightPos, int Index) { + + // If Shadows Are Not Enabled, Exit Early + if (!ReceiveShadows_) { + return 1.0f; + } + + vec4 fragPosLightSpace = LightSpaceMatrix * vec4(Object.FragPos, 1.0f); // perform perspective divide @@ -218,27 +401,99 @@ float ShadowCalculation(mat4 LightSpaceMatrix, vec3 LightPos, int Index) float currentDepth = projCoords.z; // check whether current frag pos is in shadow vec3 LightDir = normalize(LightPos - Object.FragPos); - float Bias = max(0.00 * (1.0 - dot(Object.Normal, LightDir)), 0.00025); + float Bias = max(0.00 * (1.0 - dot(Object.Normal, LightDir)), 0.0025); //float Shadow = currentDepth - Bias > closestDepth ? 1.0 : 0.0; - float Shadow = ShadowPCF(Bias, projCoords, Index, currentDepth, 2); + float Shadow = PCFSampler(Bias, projCoords, Index, currentDepth, 2); //float Shadow = ShadowPCFRandom(Bias, projCoords, Index, currentDepth, 1); if (projCoords.z > 1.0) { Shadow = 0.0f; } - if (Shadow > 1.0f) { - Shadow = 1.0f; - } else if (Shadow < 0.0f) { - Shadow = 0.0f; - } + if (Shadow > 1.0f) { + Shadow = 1.0f; + } else if (Shadow < 0.0f) { + Shadow = 0.0f; + } return 1.0f - Shadow; } +float ShadowCalculation(STRUCT_SpotLight Light) +{ + + // If Shadows Are Not Enabled, Exit Early + if (!ReceiveShadows_ || !Light.CastsShadows) { + return 1.0f; + } + + + vec4 fragPosLightSpace = Light.LightSpaceMatrix * vec4(Object.FragPos, 1.0f); + + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5f + 0.5; + + // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) + float closestDepth = texture(DepthMapArray, vec3(projCoords.xy, Light.DepthMapIndex)).r; + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + // check whether current frag pos is in shadow + vec3 LightDir = normalize(Light.Position - Object.FragPos); + + + // Generate Shadow Map Bias + int TextureSize = textureSize(DepthMapArray, 0).x; + float BiasMax = 0.0005f; + if (TextureSize <= 512) { + BiasMax = 0.003; + } else if (TextureSize <= 1024) { + BiasMax = 0.0015; + } else if (TextureSize <= 2048) { + BiasMax = 0.001; + } else if (TextureSize <= 4096) { + BiasMax = 0.00075; + } else if (TextureSize <= 8192) { + BiasMax = 0.00045; + } else if (TextureSize <= 16384) { + BiasMax = 0.00025; + } + + float Bias = max(0.00 * (1.0 - dot(Object.Normal, LightDir)), BiasMax);//0.00225); + + + // Select Correct Filter Based On Selection Uniform + float Shadow; + if (ShadowFilterType_ == 0) { // No Filtering + Shadow = currentDepth - Bias > closestDepth ? 1.0 : 0.0; + } else if (ShadowFilterType_ == 1) { // PCF Filtering + Shadow = PCFSampler(Bias, projCoords, Light.DepthMapIndex, currentDepth, ShadowFilterKernelSize_); + } else if (ShadowFilterType_ == 2) { // Poisson Filtering + Shadow = PoissonSampler(Bias, projCoords, Light.DepthMapIndex, currentDepth, ShadowFilterKernelSize_); + } else if (ShadowFilterType_ == 3) { + Shadow = StratifiedPoissonSampler(Bias, projCoords, Light.DepthMapIndex, currentDepth, ShadowFilterKernelSize_); + } else { + return 0.0f; // Return Failure, All Black) + } + + if (projCoords.z > 1.0) { + Shadow = 0.0f; + } + + if (Shadow > 1.0f) { + Shadow = 1.0f; + } else if (Shadow < 0.0f) { + Shadow = 0.0f; + } + + + return 1.0f - Shadow; +} + @@ -249,7 +504,7 @@ vec3 GetNormalFromMap(sampler2D Normal) { // Ensure That Textures Are Present/Valid, If Not, Provide Fallback vec3 SampledColor = texture(Normal, Object.TexCoords).xyz; if (!HasNormals || (SampledColor == vec3(0.0f))) { - SampledColor = vec3(0.5f, 0.5f, 1.0f); + SampledColor = vec3(0.5f, 0.5f, 1.0f); } // Use Texture Data To Calculate Normal Data @@ -378,25 +633,7 @@ STRUCT_SampledData SetSampledData() { -float ShadowCalculation(STRUCT_PointLight Light) -{ - // get vector between fragment position and light position - vec3 fragToLight = Object.FragPos - Light.Position; - // ise the fragment to light vector to sample from the depth map - float closestDepth = texture(DepthMapCubeArray, vec4(fragToLight, Light.DepthCubemapIndex)).r; - // it is currently in linear range between [0,1], let's re-transform it back to original depth value - closestDepth *= Light.MaxDistance; - // now get current linear depth as the length between the fragment and light position - float currentDepth = length(fragToLight); - // test for shadows - float bias = 0.025; // we use a much larger bias since depth is now in [near_plane, far_plane] range - float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; - // display closestDepth as debug (to visualize depth cubemap) - // FragColor = vec4(vec3(closestDepth / Light.MaxDistance), 1.0); - - return 1.0f - shadow; -} vec3 PBRPointLight(STRUCT_PointLight Light, vec3 ViewDir, vec3 Reflectance, STRUCT_SampledData Model) { @@ -494,7 +731,7 @@ vec3 PBRSpotLight(STRUCT_SpotLight Light, vec3 ViewDir, vec3 Reflectance, STRUCT } // add to outgoing radiance Lo - return ((kD * Model.Albedo.rgb / PI + specular) * radiance * NdotL * Intensity) * ShadowCalculation(Light.LightSpaceMatrix, Light.Direction, Light.DepthMapIndex); // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again + return ((kD * Model.Albedo.rgb / PI + specular) * radiance * NdotL * Intensity) * ShadowCalculation(Light); // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again } @@ -579,7 +816,7 @@ void main() { vec4 Color = Ambient + vec4(Lo, Model.Albedo.a); - // Add Emissive Texture + // Add Emissive Texture if (HasEmissive) { Color.rgb += Model.Emissive; } @@ -613,6 +850,13 @@ void main() { + + + + + + + diff --git a/Source/EditorAssets/Projects/DefaultProject/3.ERS b/Source/EditorAssets/Projects/DefaultProject/3.ERS index d3be522eee..dd447c8254 100644 --- a/Source/EditorAssets/Projects/DefaultProject/3.ERS +++ b/Source/EditorAssets/Projects/DefaultProject/3.ERS @@ -15,6 +15,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 1: @@ -31,6 +34,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 2: @@ -47,6 +53,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 3: @@ -63,6 +72,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 4: @@ -79,6 +91,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 5: @@ -95,6 +110,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 6: @@ -111,6 +129,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 7: @@ -127,6 +148,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 8: @@ -143,6 +167,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 9: @@ -159,6 +186,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 10: @@ -175,6 +205,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 11: @@ -191,6 +224,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 12: @@ -207,6 +243,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 13: @@ -223,6 +262,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 14: @@ -239,6 +281,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 15: @@ -255,6 +300,9 @@ SceneData: AssetScaleY: 0.00311163021 AssetScaleZ: 0.00311163021 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 16: @@ -271,6 +319,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 17: @@ -287,6 +338,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 18: @@ -303,6 +357,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 19: @@ -319,6 +376,9 @@ SceneData: AssetScaleY: 0.00990002044 AssetScaleZ: 0.00990002137 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 20: @@ -335,6 +395,9 @@ SceneData: AssetScaleY: 0.00736923702 AssetScaleZ: 0.00736923702 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 21: @@ -351,6 +414,9 @@ SceneData: AssetScaleY: 0.00736923702 AssetScaleZ: 0.00736923702 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 22: @@ -367,6 +433,9 @@ SceneData: AssetScaleY: 0.00736923702 AssetScaleZ: 0.00736923702 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 23: @@ -383,6 +452,9 @@ SceneData: AssetScaleY: 0.00800004043 AssetScaleZ: 0.00800004043 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 24: @@ -399,6 +471,9 @@ SceneData: AssetScaleY: 0.00800004043 AssetScaleZ: 0.00800004043 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 25: @@ -415,6 +490,9 @@ SceneData: AssetScaleY: 0.000735000009 AssetScaleZ: 0.000735000067 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 26: @@ -431,6 +509,9 @@ SceneData: AssetScaleY: 0.000735000009 AssetScaleZ: 0.000735000067 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 27: @@ -447,6 +528,9 @@ SceneData: AssetScaleY: 0.000735000009 AssetScaleZ: 0.000735000067 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 28: @@ -463,6 +547,9 @@ SceneData: AssetScaleY: 0.000735000009 AssetScaleZ: 0.000735000067 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 29: @@ -479,6 +566,9 @@ SceneData: AssetScaleY: 0.000735000009 AssetScaleZ: 0.000735000067 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 30: @@ -495,6 +585,9 @@ SceneData: AssetScaleY: 0.00380000775 AssetScaleZ: 0.00380000775 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 31: @@ -511,6 +604,9 @@ SceneData: AssetScaleY: 0.00793306623 AssetScaleZ: 0.00694000022 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 32: @@ -527,6 +623,9 @@ SceneData: AssetScaleY: 0.0082000168 AssetScaleZ: 0.0082000168 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 33: @@ -543,6 +642,9 @@ SceneData: AssetScaleY: 0.0082000168 AssetScaleZ: 0.0082000168 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 34: @@ -559,6 +661,9 @@ SceneData: AssetScaleY: 0.00832000002 AssetScaleZ: 0.00728000002 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 35: @@ -575,6 +680,9 @@ SceneData: AssetScaleY: 0.00380000775 AssetScaleZ: 0.00380000775 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 36: @@ -591,6 +699,9 @@ SceneData: AssetScaleY: 0.00293800584 AssetScaleZ: 0.00293800584 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 37: @@ -607,6 +718,9 @@ SceneData: AssetScaleY: 0.00293800584 AssetScaleZ: 0.00293800584 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 38: @@ -623,6 +737,9 @@ SceneData: AssetScaleY: 0.00736923702 AssetScaleZ: 0.00736923702 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 39: @@ -639,6 +756,9 @@ SceneData: AssetScaleY: 0.00736923702 AssetScaleZ: 0.00736923702 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 40: @@ -655,6 +775,9 @@ SceneData: AssetScaleY: 0.00293800584 AssetScaleZ: 0.00293800584 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 41: @@ -671,6 +794,9 @@ SceneData: AssetScaleY: 0.00293800584 AssetScaleZ: 0.00293800584 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 42: @@ -687,6 +813,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 43: @@ -703,6 +832,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 44: @@ -719,6 +851,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 45: @@ -735,6 +870,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 46: @@ -751,6 +889,9 @@ SceneData: AssetScaleY: 0.00280800601 AssetScaleZ: 0.00280800601 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 47: @@ -767,6 +908,9 @@ SceneData: AssetScaleY: 0.00990002044 AssetScaleZ: 0.00990002137 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 48: @@ -783,6 +927,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 49: @@ -799,6 +946,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 50: @@ -815,6 +965,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 51: @@ -831,6 +984,9 @@ SceneData: AssetScaleY: 0.0100000501 AssetScaleZ: 0.0100000501 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 52: @@ -847,6 +1003,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 53: @@ -863,6 +1022,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 54: @@ -879,6 +1041,9 @@ SceneData: AssetScaleY: 0.0199999996 AssetScaleZ: 0.0199999996 FlipTextures: true + CastDynamicShadows: true + CastStaticShadows: true + ReceiveShadows: true AttachedScripts: {} 55: @@ -995,8 +1160,8 @@ SceneData: PosY: 1.5959357 PosZ: 6.00342846 RotX: 209.56749 - RotY: 59.9117813 - RotZ: 160.184723 + RotY: 59.9117851 + RotZ: 165.184708 Intensity: 25 MaxDistance: 10 CutOff: 103 @@ -1027,12 +1192,12 @@ SceneData: ColorRed: 1 ColorGreen: 1 ColorBlue: 1 - PosX: -0.849999964 - PosY: 1.5 + PosX: -0.74999994 + PosY: 1.60000002 PosZ: -4.8931241 - RotX: 47.6549835 - RotY: 47.9395943 - RotZ: 4.55612373 + RotX: 48.318615 + RotY: 52.9613876 + RotZ: 10.0683851 Intensity: 25 MaxDistance: 10 CutOff: 95 @@ -1045,12 +1210,12 @@ SceneData: ColorRed: 1 ColorGreen: 1 ColorBlue: 1 - PosX: 2.97785139 + PosX: 2.87785149 PosY: 1.5 PosZ: -4.70444107 - RotX: 4.07153368 - RotY: 59.641552 - RotZ: 250.978882 + RotX: 11.295084 + RotY: 50.5678635 + RotZ: 239.557556 Intensity: 25 MaxDistance: 15 CutOff: 77