diff --git a/Source/Editor/Analytics/EditorAnalytics.cpp b/Source/Editor/Analytics/EditorAnalytics.cpp index 83c0b1f85..ed17b6249 100644 --- a/Source/Editor/Analytics/EditorAnalytics.cpp +++ b/Source/Editor/Analytics/EditorAnalytics.cpp @@ -103,6 +103,8 @@ void EditorAnalytics::StartSession() { UA_DOCUMENT_TITLE, 0, "Flax Editor" }, #if PLATFORM_WINDOWS { UA_USER_AGENT, 0, "Windows " FLAXENGINE_VERSION_TEXT }, +#elif PLATFORM_LINUX + { UA_USER_AGENT, 0, "Linux " FLAXENGINE_VERSION_TEXT }, #else #error "Unknown platform" #endif diff --git a/Source/Engine/CSG/CSGMesh.Build.cpp b/Source/Engine/CSG/CSGMesh.Build.cpp index fdd481f0f..53d634c88 100644 --- a/Source/Engine/CSG/CSGMesh.Build.cpp +++ b/Source/Engine/CSG/CSGMesh.Build.cpp @@ -93,6 +93,7 @@ void CSG::Mesh::Build(Brush* parentBrush) for (int32 planeIndex3 = planeIndex2 + 1; planeIndex3 < surfacesCount; planeIndex3++) { Surface plane3 = _surfaces[planeIndex3]; + int32 vertexIndex; // Calculate the intersection point Vector3 vertex = Plane::Intersection(plane1, plane2, plane3); @@ -127,7 +128,7 @@ void CSG::Mesh::Build(Brush* parentBrush) goto SkipIntersection; } - int32 vertexIndex = _vertices.Count(); + vertexIndex = _vertices.Count(); _vertices.Add(vertex); // Add intersection point to our list diff --git a/Source/Engine/Platform/Android/AndroidPlatformSettings.h b/Source/Engine/Platform/Android/AndroidPlatformSettings.h index 3a1c1f736..000b415a5 100644 --- a/Source/Engine/Platform/Android/AndroidPlatformSettings.h +++ b/Source/Engine/Platform/Android/AndroidPlatformSettings.h @@ -52,7 +52,7 @@ public: } }; -#if PLATFORM_LINUX +#if PLATFORM_ANDROID typedef AndroidPlatformSettings PlatformSettings; #endif diff --git a/Source/Engine/ShadersCompilation/ShadersCompilation.Build.cs b/Source/Engine/ShadersCompilation/ShadersCompilation.Build.cs index f8f885315..6a47b0c23 100644 --- a/Source/Engine/ShadersCompilation/ShadersCompilation.Build.cs +++ b/Source/Engine/ShadersCompilation/ShadersCompilation.Build.cs @@ -51,6 +51,9 @@ public class ShadersCompilation : EngineModule //options.PrivateDependencies.Add("ShaderCompilerOGL"); options.PrivateDependencies.Add("ShaderCompilerVulkan"); break; + case TargetPlatform.Linux: + options.PrivateDependencies.Add("ShaderCompilerVulkan"); + break; default: throw new InvalidPlatformException(options.Platform.Target); } diff --git a/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp b/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp index ee17a6989..ca933df0f 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp @@ -7,7 +7,6 @@ #include "Engine/ContentImporters/AssetsImportingManager.h" #include "Engine/ContentImporters/ImportTexture.h" #include "Engine/Graphics/PixelFormatExtensions.h" -#include ShadowsOfMordor::Builder::LightmapBuildCache::~LightmapBuildCache() { diff --git a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp index c64a80005..2f84b0bf0 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp @@ -8,13 +8,313 @@ #include "Engine/Graphics/RenderTargetPool.h" #define STEPS_SLEEP_TIME 20 -#define RUN_STEP(handler) handler(); if (checkBuildCancelled()) goto BUILDING_END; Platform::Sleep(STEPS_SLEEP_TIME) +#define RUN_STEP(handler) handler(); if (checkBuildCancelled()) return true; Platform::Sleep(STEPS_SLEEP_TIME) + +bool ShadowsOfMordor::Builder::doWorkInner(DateTime buildStart) +{ +#if HEMISPHERES_BAKE_STATE_SAVE + _lastStateSaveTime = DateTime::Now(); + _firstStateSave = true; + + // Try to load the state that was cached during hemispheres rendering (restore rendering in case of GPU driver crash) + if (loadState()) + { + reportProgress(BuildProgressStep::RenderHemispheres, 0.0f); + const int32 firstScene = _workerActiveSceneIndex; + { + // Wait for lightmaps to be fully loaded + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) + { + LOG(Error, "Failed to load lightmap textures."); + _wasBuildCalled = false; + _isActive = false; + return true; + } + + if (checkBuildCancelled()) + return true; + } + + // Continue the hemispheres rendering for the last scene from the cached position + { + _workerActiveSceneIndex = firstScene; + if (runStage(RenderHemispheres, false)) + return true; + + // Fill black holes with blurred data to prevent artifacts on the edges + _workerStagePosition0 = 0; + if (runStage(PostprocessLightmaps)) + return true; + + // Wait for GPU commands to sync + if (waitForJobDataSync()) + return true; + + // Update lightmaps textures + _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); + } + for (_workerActiveSceneIndex = firstScene + 1; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + // Skip scenes without any lightmaps + if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) + continue; + + // Clear hemispheres target + _workerStagePosition0 = 0; + if (runStage(ClearLightmapData)) + return true; + + // Render all registered Hemispheres rendering + _workerStagePosition0 = 0; + if (runStage(RenderHemispheres)) + return true; + + // Fill black holes with blurred data to prevent artifacts on the edges + _workerStagePosition0 = 0; + if (runStage(PostprocessLightmaps)) + return true; + + // Wait for GPU commands to sync + if (waitForJobDataSync()) + return true; + + // Update lightmaps textures + _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); + } + } + for (int32 bounce = _giBounceRunningIndex + 1; bounce < _bounceCount; bounce++) + { + _giBounceRunningIndex = bounce; + + // Wait for lightmaps to be fully loaded + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) + { + LOG(Error, "Failed to load lightmap textures."); + _wasBuildCalled = false; + _isActive = false; + return true; + } + if (checkBuildCancelled()) + return true; + } + + // Render bounce for every scene separately + for (_workerActiveSceneIndex = firstScene; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + // Skip scenes without any lightmaps + if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) + continue; + + // Clear hemispheres target + _workerStagePosition0 = 0; + if (runStage(ClearLightmapData)) + return true; + + // Render all registered Hemispheres rendering + _workerStagePosition0 = 0; + if (runStage(RenderHemispheres)) + return true; + + // Fill black holes with blurred data to prevent artifacts on the edges + _workerStagePosition0 = 0; + if (runStage(PostprocessLightmaps)) + return true; + + // Wait for GPU commands to sync + if (waitForJobDataSync()) + return true; + + // Update lightmaps textures + _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); + } + } + reportProgress(BuildProgressStep::RenderHemispheres, 1.0f); + return true; + } +#endif + + // Compute the final weight for integration + { + float weightSum = 0.0f; + for (uint32 y = 0; y < HEMISPHERES_RESOLUTION; y++) + { + const float v = (float(y) / float(HEMISPHERES_RESOLUTION)) * 2.0f - 1.0f; + for (uint32 x = 0; x < HEMISPHERES_RESOLUTION; x++) + { + const float u = (float(x) / float(HEMISPHERES_RESOLUTION)) * 2.0f - 1.0f; + const float t = 1.0f + u * u + v * v; + const float weight = 4.0f / (Math::Sqrt(t) * t); + weightSum += weight; + } + } + weightSum *= 6; + _hemisphereTexelsTotalWeight = (4.0f * PI) / weightSum; + } + + // Initialize the lightmaps and pack entries to the charts + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + RUN_STEP(cacheEntries); + RUN_STEP(generateCharts); + RUN_STEP(packCharts); + RUN_STEP(updateLightmaps); + RUN_STEP(updateEntries); + } + + // TODO: if settings require wait for asset dependencies to all materials and models be loaded (maybe only for higher quality profiles) + + // Generate hemispheres cache and prepare for baking + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + // Wait for lightmaps to be fully loaded + if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) + { + LOG(Error, "Failed to load lightmap textures."); + _wasBuildCalled = false; + _isActive = false; + return true; + } + + ASSERT(_cachePositions == nullptr && _cacheNormals == nullptr); + const int32 atlasSize = (int32)_scenes[_workerActiveSceneIndex]->GetSettings().AtlasSize; + auto tempDesc = GPUTextureDescription::New2D(atlasSize, atlasSize, HemispheresFormatToPixelFormat[CACHE_POSITIONS_FORMAT]); + _cachePositions = RenderTargetPool::Get(tempDesc); + tempDesc.Format = HemispheresFormatToPixelFormat[CACHE_NORMALS_FORMAT]; + _cacheNormals = RenderTargetPool::Get(tempDesc); + if (_cachePositions == nullptr || _cacheNormals == nullptr) + return true; + + generateHemispheres(); + + RenderTargetPool::Release(_cachePositions); + _cachePositions = nullptr; + RenderTargetPool::Release(_cacheNormals); + _cacheNormals = nullptr; + + if (checkBuildCancelled()) + return true; + Platform::Sleep(STEPS_SLEEP_TIME); + } + + // Prepare before actual baking + int32 hemispheresCount = 0; + int32 mergedHemispheresCount = 0; + int32 bounceCount = 0; + int32 lightmapsCount = 0; + int32 entriesCount = 0; + for (int32 sceneIndex = 0; sceneIndex < _scenes.Count(); sceneIndex++) + { + auto& scene = *_scenes[sceneIndex]; + hemispheresCount += scene.HemispheresCount; + mergedHemispheresCount += scene.MergedHemispheresCount; + lightmapsCount += scene.Lightmaps.Count(); + entriesCount += scene.Entries.Count(); + bounceCount = Math::Max(bounceCount, scene.GetSettings().BounceCount); + + // Cleanup unused data to reduce memory usage + scene.Entries.Resize(0); + scene.Charts.Resize(0); + for (auto& lightmap : scene.Lightmaps) + lightmap.Entries.Resize(0); + } + _bounceCount = bounceCount; + LOG(Info, "Rendering {0} hemispheres in {1} bounce(s) (merged: {2})", hemispheresCount, bounceCount, mergedHemispheresCount); + if (bounceCount <= 0 || hemispheresCount <= 0) + { + LOG(Warning, "No data to render"); + return true; + } + + // For each bounce + for (int32 bounce = 0; bounce < _bounceCount; bounce++) + { + _giBounceRunningIndex = bounce; + + // Wait for lightmaps to be fully loaded + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) + { + LOG(Error, "Failed to load lightmap textures."); + _wasBuildCalled = false; + _isActive = false; + return true; + } + if (checkBuildCancelled()) + return true; + } + + // Render bounce for every scene separately + for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) + { + // Skip scenes without any lightmaps + if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) + continue; + + // Clear hemispheres target + _workerStagePosition0 = 0; + if (runStage(ClearLightmapData)) + return true; + + // Render all registered Hemispheres rendering + _workerStagePosition0 = 0; + if (runStage(RenderHemispheres)) + return true; + + // Fill black holes with blurred data to prevent artifacts on the edges + _workerStagePosition0 = 0; + if (runStage(PostprocessLightmaps)) + return true; + + // Wait for GPU commands to sync + if (waitForJobDataSync()) + return true; + + // Update lightmaps textures + _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); + } + } + + reportProgress(BuildProgressStep::RenderHemispheres, 1.0f); + +#if DEBUG_EXPORT_HEMISPHERES_PREVIEW + for (int32 sceneIndex = 0; sceneIndex < _scenes.Count(); sceneIndex++) + downloadDebugHemisphereAtlases(_scenes[sceneIndex]); +#endif + + // References: + // "Optimization of numerical calculations execution time in multiprocessor systems" - Wojciech Figat + // https://knarkowicz.wordpress.com/2014/07/20/lightmapping-in-anomaly-2-mobile/ + // http://the-witness.net/news/2010/09/hemicube-rendering-and-integration/ + // http://the-witness.net/news/2010/03/graphics-tech-texture-parameterization/ + // http://the-witness.net/news/2010/03/graphics-tech-lighting-comparison/ + + // Some ideas: + // - render hemispheres to atlas or sth and batch integration and downscalling for multiply texels + // - use conservative rasterization for dx12 instead of blur or MSAA for all platforms + // - use hemisphere depth buffer to compute AO + + // End + const int32 hemispheresRenderedCount = hemispheresCount * bounceCount; + DateTime buildEnd = DateTime::NowUTC(); + LOG(Info, "Building lightmap finished! Time: {0}s, Lightmaps: {1}, Entries: {2}, Hemicubes rendered: {3}", + static_cast((buildEnd - buildStart).GetTotalSeconds()), + lightmapsCount, + entriesCount, + hemispheresRenderedCount); + + return false; +} int32 ShadowsOfMordor::Builder::doWork() { // Start bool buildFailed = true; - DateTime buildEnd, buildStart = DateTime::NowUTC(); + DateTime buildStart = DateTime::NowUTC(); _lastStep = BuildProgressStep::CacheEntries; _lastStepStart = buildStart; _hemispheresPerJob = HEMISPHERES_PER_JOB_MIN; @@ -84,309 +384,14 @@ int32 ShadowsOfMordor::Builder::doWork() } } + // Run IsBakingLightmaps = true; - -#if HEMISPHERES_BAKE_STATE_SAVE - _lastStateSaveTime = DateTime::Now(); - _firstStateSave = true; - - // Try to load the state that was cached during hemispheres rendering (restore rendering in case of GPU driver crash) - if (loadState()) + buildFailed = doWorkInner(buildStart); + if (buildFailed && !checkBuildCancelled()) { - reportProgress(BuildProgressStep::RenderHemispheres, 0.0f); - const int32 firstScene = _workerActiveSceneIndex; - { - // Wait for lightmaps to be fully loaded - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) - { - LOG(Error, "Failed to load lightmap textures."); - _wasBuildCalled = false; - _isActive = false; - OnBuildFinished(buildFailed); - return 0; - } - - if (checkBuildCancelled()) - goto BUILDING_END; - } - - // Continue the hemispheres rendering for the last scene from the cached position - { - _workerActiveSceneIndex = firstScene; - if (runStage(RenderHemispheres, false)) - goto BUILDING_END; - - // Fill black holes with blurred data to prevent artifacts on the edges - _workerStagePosition0 = 0; - if (runStage(PostprocessLightmaps)) - goto BUILDING_END; - - // Wait for GPU commands to sync - if (waitForJobDataSync()) - goto BUILDING_END; - - // Update lightmaps textures - _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); - } - for (_workerActiveSceneIndex = firstScene + 1; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - // Skip scenes without any lightmaps - if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) - continue; - - // Clear hemispheres target - _workerStagePosition0 = 0; - if (runStage(ClearLightmapData)) - goto BUILDING_END; - - // Render all registered Hemispheres rendering - _workerStagePosition0 = 0; - if (runStage(RenderHemispheres)) - goto BUILDING_END; - - // Fill black holes with blurred data to prevent artifacts on the edges - _workerStagePosition0 = 0; - if (runStage(PostprocessLightmaps)) - goto BUILDING_END; - - // Wait for GPU commands to sync - if (waitForJobDataSync()) - goto BUILDING_END; - - // Update lightmaps textures - _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); - } - } - for (int32 bounce = _giBounceRunningIndex + 1; bounce < _bounceCount; bounce++) - { - _giBounceRunningIndex = bounce; - - // Wait for lightmaps to be fully loaded - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) - { - LOG(Error, "Failed to load lightmap textures."); - _wasBuildCalled = false; - _isActive = false; - OnBuildFinished(buildFailed); - return 0; - } - if (checkBuildCancelled()) - goto BUILDING_END; - } - - // Render bounce for every scene separately - for (_workerActiveSceneIndex = firstScene; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - // Skip scenes without any lightmaps - if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) - continue; - - // Clear hemispheres target - _workerStagePosition0 = 0; - if (runStage(ClearLightmapData)) - goto BUILDING_END; - - // Render all registered Hemispheres rendering - _workerStagePosition0 = 0; - if (runStage(RenderHemispheres)) - goto BUILDING_END; - - // Fill black holes with blurred data to prevent artifacts on the edges - _workerStagePosition0 = 0; - if (runStage(PostprocessLightmaps)) - goto BUILDING_END; - - // Wait for GPU commands to sync - if (waitForJobDataSync()) - goto BUILDING_END; - - // Update lightmaps textures - _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); - } - } - reportProgress(BuildProgressStep::RenderHemispheres, 1.0f); - goto BUILDING_END; + OnBuildFinished(buildFailed); + return 0; } -#endif - - // Compute the final weight for integration - { - float weightSum = 0.0f; - for (uint32 y = 0; y < HEMISPHERES_RESOLUTION; y++) - { - const float v = (float(y) / float(HEMISPHERES_RESOLUTION)) * 2.0f - 1.0f; - for (uint32 x = 0; x < HEMISPHERES_RESOLUTION; x++) - { - const float u = (float(x) / float(HEMISPHERES_RESOLUTION)) * 2.0f - 1.0f; - const float t = 1.0f + u * u + v * v; - const float weight = 4.0f / (Math::Sqrt(t) * t); - weightSum += weight; - } - } - weightSum *= 6; - _hemisphereTexelsTotalWeight = (4.0f * PI) / weightSum; - } - - // Initialize the lightmaps and pack entries to the charts - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - RUN_STEP(cacheEntries); - RUN_STEP(generateCharts); - RUN_STEP(packCharts); - RUN_STEP(updateLightmaps); - RUN_STEP(updateEntries); - } - - // TODO: if settings require wait for asset dependencies to all materials and models be loaded (maybe only for higher quality profiles) - - // Generate hemispheres cache and prepare for baking - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - // Wait for lightmaps to be fully loaded - if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) - { - LOG(Error, "Failed to load lightmap textures."); - _wasBuildCalled = false; - _isActive = false; - OnBuildFinished(buildFailed); - return 0; - } - - ASSERT(_cachePositions == nullptr && _cacheNormals == nullptr); - const int32 atlasSize = (int32)_scenes[_workerActiveSceneIndex]->GetSettings().AtlasSize; - auto tempDesc = GPUTextureDescription::New2D(atlasSize, atlasSize, HemispheresFormatToPixelFormat[CACHE_POSITIONS_FORMAT]); - _cachePositions = RenderTargetPool::Get(tempDesc); - tempDesc.Format = HemispheresFormatToPixelFormat[CACHE_NORMALS_FORMAT]; - _cacheNormals = RenderTargetPool::Get(tempDesc); - if (_cachePositions == nullptr || _cacheNormals == nullptr) - goto BUILDING_END; - - generateHemispheres(); - - RenderTargetPool::Release(_cachePositions); - _cachePositions = nullptr; - RenderTargetPool::Release(_cacheNormals); - _cacheNormals = nullptr; - - if (checkBuildCancelled()) - goto BUILDING_END; - Platform::Sleep(STEPS_SLEEP_TIME); - } - - // Prepare before actual baking - int32 hemispheresCount = 0; - int32 mergedHemispheresCount = 0; - int32 bounceCount = 0; - int32 lightmapsCount = 0; - int32 entriesCount = 0; - for (int32 sceneIndex = 0; sceneIndex < _scenes.Count(); sceneIndex++) - { - auto& scene = *_scenes[sceneIndex]; - hemispheresCount += scene.HemispheresCount; - mergedHemispheresCount += scene.MergedHemispheresCount; - lightmapsCount += scene.Lightmaps.Count(); - entriesCount += scene.Entries.Count(); - bounceCount = Math::Max(bounceCount, scene.GetSettings().BounceCount); - - // Cleanup unused data to reduce memory usage - scene.Entries.Resize(0); - scene.Charts.Resize(0); - for (auto& lightmap : scene.Lightmaps) - lightmap.Entries.Resize(0); - } - _bounceCount = bounceCount; - LOG(Info, "Rendering {0} hemispheres in {1} bounce(s) (merged: {2})", hemispheresCount, bounceCount, mergedHemispheresCount); - if (bounceCount <= 0 || hemispheresCount <= 0) - { - LOG(Warning, "No data to render"); - goto BUILDING_END; - } - - // For each bounce - for (int32 bounce = 0; bounce < _bounceCount; bounce++) - { - _giBounceRunningIndex = bounce; - - // Wait for lightmaps to be fully loaded - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - if (_scenes[_workerActiveSceneIndex]->WaitForLightmaps()) - { - LOG(Error, "Failed to load lightmap textures."); - _wasBuildCalled = false; - _isActive = false; - OnBuildFinished(buildFailed); - return 0; - } - if (checkBuildCancelled()) - goto BUILDING_END; - } - - // Render bounce for every scene separately - for (_workerActiveSceneIndex = 0; _workerActiveSceneIndex < _scenes.Count(); _workerActiveSceneIndex++) - { - // Skip scenes without any lightmaps - if (_scenes[_workerActiveSceneIndex]->Lightmaps.IsEmpty()) - continue; - - // Clear hemispheres target - _workerStagePosition0 = 0; - if (runStage(ClearLightmapData)) - goto BUILDING_END; - - // Render all registered Hemispheres rendering - _workerStagePosition0 = 0; - if (runStage(RenderHemispheres)) - goto BUILDING_END; - - // Fill black holes with blurred data to prevent artifacts on the edges - _workerStagePosition0 = 0; - if (runStage(PostprocessLightmaps)) - goto BUILDING_END; - - // Wait for GPU commands to sync - if (waitForJobDataSync()) - goto BUILDING_END; - - // Update lightmaps textures - _scenes[_workerActiveSceneIndex]->UpdateLightmaps(); - } - } - - reportProgress(BuildProgressStep::RenderHemispheres, 1.0f); - -#if DEBUG_EXPORT_HEMISPHERES_PREVIEW - for (int32 sceneIndex = 0; sceneIndex < _scenes.Count(); sceneIndex++) - downloadDebugHemisphereAtlases(_scenes[sceneIndex]); -#endif - - // References: - // "Optimization of numerical calculations execution time in multiprocessor systems" - Wojciech Figat - // https://knarkowicz.wordpress.com/2014/07/20/lightmapping-in-anomaly-2-mobile/ - // http://the-witness.net/news/2010/09/hemicube-rendering-and-integration/ - // http://the-witness.net/news/2010/03/graphics-tech-texture-parameterization/ - // http://the-witness.net/news/2010/03/graphics-tech-lighting-comparison/ - - // Some ideas: - // - render hemispheres to atlas or sth and batch integration and downscalling for multiply texels - // - use conservative rasterization for dx12 instead of blur or MSAA for all platforms - // - use hemisphere depth buffer to compute AO - - // End - const int32 hemispheresRenderedCount = hemispheresCount * bounceCount; - buildEnd = DateTime::NowUTC(); - LOG(Info, "Building lightmap finished! Time: {0}s, Lightmaps: {1}, Entries: {2}, Hemicubes rendered: {3}", - static_cast((buildEnd - buildStart).GetTotalSeconds()), - lightmapsCount, - entriesCount, - hemispheresRenderedCount); - buildFailed = false; - -BUILDING_END: // Cleanup cached data reportProgress(BuildProgressStep::Cleanup, 0.0f); diff --git a/Source/Engine/ShadowsOfMordor/Builder.h b/Source/Engine/ShadowsOfMordor/Builder.h index 0fec48555..d796f825d 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.h +++ b/Source/Engine/ShadowsOfMordor/Builder.h @@ -313,6 +313,7 @@ namespace ShadowsOfMordor bool waitForJobDataSync(); static bool sortCharts(const LightmapUVsChart& a, const LightmapUVsChart& b); + bool doWorkInner(DateTime buildStart); int32 doWork(); void cacheEntries(); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Build.cs b/Source/Engine/Tools/ModelTool/ModelTool.Build.cs index 1211116e1..1e9811400 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Build.cs +++ b/Source/Engine/Tools/ModelTool/ModelTool.Build.cs @@ -49,8 +49,17 @@ public class ModelTool : EngineModule options.PrivateDependencies.Add("TextureTool"); options.PrivateDefinitions.Add("COMPILE_WITH_ASSETS_IMPORTER"); - options.PrivateDependencies.Add("DirectXMesh"); - options.PrivateDependencies.Add("UVAtlas"); + switch (options.Platform.Target) + { + case TargetPlatform.Windows: + options.PrivateDependencies.Add("DirectXMesh"); + options.PrivateDependencies.Add("UVAtlas"); + break; + case TargetPlatform.Linux: + break; + default: throw new InvalidPlatformException(options.Platform.Target); + } + options.PrivateDependencies.Add("meshoptimizer"); options.PublicDefinitions.Add("COMPILE_WITH_MODEL_TOOL"); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index f95c219c6..e51b086b6 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -257,7 +257,7 @@ void OptimizeCurve(LinearCurve& curve) { auto& oldKeyframes = curve.GetKeyframes(); const int32 keyCount = oldKeyframes.Count(); - LinearCurve::KeyFrameCollection newKeyframes(keyCount); + typename LinearCurve::KeyFrameCollection newKeyframes(keyCount); bool lastWasEqual = false; for (int32 i = 0; i < keyCount; i++) diff --git a/Source/Engine/Visject/ShaderGraph.h b/Source/Engine/Visject/ShaderGraph.h index 2b444f686..ba0bd6a21 100644 --- a/Source/Engine/Visject/ShaderGraph.h +++ b/Source/Engine/Visject/ShaderGraph.h @@ -151,7 +151,7 @@ public: public: // [Graph] - bool onNodeLoaded(Node* n) override + bool onNodeLoaded(NodeType* n) override { // Check if this node needs a state or data cache switch (n->GroupID) diff --git a/Source/ThirdParty/curl/curl.Build.cs b/Source/ThirdParty/curl/curl.Build.cs index fdd06396f..5f39b13de 100644 --- a/Source/ThirdParty/curl/curl.Build.cs +++ b/Source/ThirdParty/curl/curl.Build.cs @@ -34,6 +34,8 @@ public class curl : DepsModule options.OutputFiles.Add("wldap32.lib"); options.OutputFiles.Add("crypt32.lib"); break; + case TargetPlatform.Linux: + break; default: throw new InvalidPlatformException(options.Platform.Target); } }