From 07f58558e35dd3acad541a523f6a96f8e6790fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Jech?= Date: Mon, 21 Dec 2020 03:58:52 +0100 Subject: [PATCH 01/11] Force proper extension if manually specified by user during asset creation --- Source/Editor/Windows/ContentWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 1cf3a24f7..acea1e665 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -318,7 +318,7 @@ namespace FlaxEditor.Windows // Cache data var extension = Path.GetExtension(item.Path); - var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension); + var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, Path.ChangeExtension(newShortName, extension)); // Check if was renaming mock element // Note: we create `_newElement` and then rename it to create new asset From 5e239f5d87458380c2e0f2af4383c1fd7dabeef6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 12:57:00 +0100 Subject: [PATCH 02/11] Fix code style (cherry picked from commit 16cd75d1792e5b148fd7841312906ae9cecb515c) --- Source/Engine/Core/Config/GameSettings.cpp | 10 ++---- .../GraphicsDevice/Vulkan/CmdBufferVulkan.cpp | 4 +-- Source/Engine/GraphicsDevice/Vulkan/Config.h | 11 ------ .../Vulkan/GPUAdapterVulkan.cpp | 13 ------- .../GraphicsDevice/Vulkan/GPUAdapterVulkan.h | 12 ------- .../Vulkan/GPUDeviceVulkan.Layers.cpp | 7 ---- .../Vulkan/GPUSwapChainVulkan.cpp | 24 ------------- .../Vulkan/GPUSwapChainVulkan.h | 9 ----- .../Vulkan/Linux/LinuxVulkanPlatform.h | 1 - .../GraphicsDevice/Vulkan/RenderToolsVulkan.h | 34 +++++++------------ 10 files changed, 17 insertions(+), 108 deletions(-) diff --git a/Source/Engine/Core/Config/GameSettings.cpp b/Source/Engine/Core/Config/GameSettings.cpp index b87c380aa..254921e6b 100644 --- a/Source/Engine/Core/Config/GameSettings.cpp +++ b/Source/Engine/Core/Config/GameSettings.cpp @@ -78,13 +78,10 @@ bool GameSettings::Load() if (id.IsValid()) \ { \ AssetReference subAsset = Content::LoadAsync(id); \ - if (subAsset) \ + if (subAsset && !subAsset->WaitForLoaded()) \ { \ - if (!subAsset->WaitForLoaded()) \ - { \ - settingsType::Instance()->Deserialize(*subAsset->Data, nullptr); \ - settingsType::Instance()->Apply(); \ - } \ + settingsType::Instance()->Deserialize(*subAsset->Data, nullptr); \ + settingsType::Instance()->Apply(); \ } \ else \ { LOG(Warning, "Cannot load " nodeName " settings"); } \ @@ -143,7 +140,6 @@ bool GameSettings::Load() LOAD_SETTINGS("Navigation", NavigationSettings); // Load platform settings - // TODO: refactor platform settings impl to be more modular (better multi-platform handling) #if PLATFORM_WINDOWS LOAD_SETTINGS("WindowsPlatform", WindowsPlatformSettings); #endif diff --git a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp index a2dbb7733..a143f7dd8 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp @@ -24,14 +24,12 @@ void CmdBufferVulkan::Begin() RenderToolsVulkan::ZeroStruct(beginInfo, VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; VALIDATE_VULKAN_RESULT(vkBeginCommandBuffer(_commandBufferHandle, &beginInfo)); - -#if VULKAN_USE_DESCRIPTOR_POOL_MANAGER + // Acquire a descriptor pool set on if (_descriptorPoolSetContainer == nullptr) { AcquirePoolSet(); } -#endif _state = State::IsInsideBegin; diff --git a/Source/Engine/GraphicsDevice/Vulkan/Config.h b/Source/Engine/GraphicsDevice/Vulkan/Config.h index 28ba0bc7b..a3bb1662c 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Config.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Config.h @@ -23,29 +23,18 @@ /// #define VULKAN_RESOURCE_DELETE_SAFE_FRAMES_COUNT 10 -// Enables the VK_LAYER_LUNARG_api_dump layer and the report VK_DEBUG_REPORT_INFORMATION_BIT_EXT flag #define VULKAN_ENABLE_API_DUMP 0 - #define VULKAN_RESET_QUERY_POOLS 0 - #define VULKAN_HASH_POOLS_WITH_TYPES_USAGE_ID 1 #ifndef VULKAN_USE_DEBUG_LAYER #define VULKAN_USE_DEBUG_LAYER GPU_ENABLE_DIAGNOSTICS #endif -#ifndef VULKAN_USE_DESCRIPTOR_POOL_MANAGER -#define VULKAN_USE_DESCRIPTOR_POOL_MANAGER 1 -#endif - #ifndef VULKAN_HAS_PHYSICAL_DEVICE_PROPERTIES2 #define VULKAN_HAS_PHYSICAL_DEVICE_PROPERTIES2 0 #endif -#ifndef VULKAN_ENABLE_DESKTOP_HMD_SUPPORT -#define VULKAN_ENABLE_DESKTOP_HMD_SUPPORT 0 -#endif - #ifdef VK_KHR_maintenance1 #define VULKAN_SUPPORTS_MAINTENANCE_LAYER1 1 #else diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.cpp index 982878ce0..4d451fa52 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.cpp @@ -4,24 +4,11 @@ #include "GPUAdapterVulkan.h" #include "GPUDeviceVulkan.h" -#include "RenderToolsVulkan.h" GPUAdapterVulkan::GPUAdapterVulkan(VkPhysicalDevice gpu) : Gpu(gpu) { - // Query device information vkGetPhysicalDeviceProperties(gpu, &GpuProps); -#if VULKAN_ENABLE_DESKTOP_HMD_SUPPORT - if (GPUDeviceVulkan::OptionalDeviceExtensions.HasKHRGetPhysicalDeviceProperties2) - { - VkPhysicalDeviceProperties2KHR GpuProps2; - RenderToolsVulkan::ZeroStruct(GpuProps2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR); - GpuProps2.pNext = &GpuProps2; - RenderToolsVulkan::ZeroStruct(GpuIdProps, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR); - vkGetPhysicalDeviceProperties2KHR(Gpu, &GpuProps2); - } -#endif - Description = GpuProps.deviceName; } diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h index 559eea7ce..17a9212e7 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h @@ -33,9 +33,6 @@ public: { Gpu = other.Gpu; GpuProps = other.GpuProps; -#if VULKAN_ENABLE_DESKTOP_HMD_SUPPORT - GpuIdProps = other.GpuIdProps; -#endif Description = other.Description; return *this; } @@ -58,15 +55,6 @@ public: /// VkPhysicalDeviceProperties GpuProps; -#if VULKAN_ENABLE_DESKTOP_HMD_SUPPORT - - /// - /// The GPU device extended properties. - /// - VkPhysicalDeviceIDPropertiesKHR GpuIdProps; - -#endif - /// /// The GPU description. /// diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp index 65451ca81..88c30d660 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp @@ -34,10 +34,6 @@ static const char* GValidationLayers[] = static const char* GInstanceExtensions[] = { -#if VULKAN_ENABLE_DESKTOP_HMD_SUPPORT - VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, -#endif #if VULKAN_SUPPORTS_VALIDATION_CACHE VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, #endif @@ -50,9 +46,6 @@ static const char* GDeviceExtensions[] = #if VULKAN_SUPPORTS_MAINTENANCE_LAYER1 VK_KHR_MAINTENANCE1_EXTENSION_NAME, #endif -#if VULKAN_SUPPORTS_MAINTENANCE_LAYER2 - VK_KHR_MAINTENANCE2_EXTENSION_NAME, -#endif #if VULKAN_SUPPORTS_VALIDATION_CACHE VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, #endif diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp index ca8af3873..6354e9956 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp @@ -17,9 +17,6 @@ void BackBufferVulkan::Setup(GPUSwapChainVulkan* window, VkImage backbuffer, Pix Device = window->GetDevice(); Handle.Init(window->GetDevice(), this, backbuffer, 1, format, MSAALevel::None, extent, VK_IMAGE_VIEW_TYPE_2D); -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - ImageAcquiredFence = Device->FenceManager.AllocateFence(true); -#endif RenderingDoneSemaphore = New(Device); ImageAcquiredSemaphore = New(Device); } @@ -27,9 +24,6 @@ void BackBufferVulkan::Setup(GPUSwapChainVulkan* window, VkImage backbuffer, Pix void BackBufferVulkan::Release() { Handle.Release(); -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - Device->FenceManager.ReleaseFence(ImageAcquiredFence); -#endif Delete(RenderingDoneSemaphore); Delete(ImageAcquiredSemaphore); } @@ -509,19 +503,9 @@ int32 GPUSwapChainVulkan::AcquireImageIndex(SemaphoreVulkan** outSemaphore) { ASSERT(_swapChain && _backBuffers.HasItems()); - // Get the index of the next swap chain image to render to. - // Wait with an "infinite" timeout, the function will block until an image is ready. - // The semaphore will get signaled when the image is ready (upon function return). - uint32 imageIndex = 0; const int32 prevSemaphoreIndex = _semaphoreIndex; _semaphoreIndex = (_semaphoreIndex + 1) % _backBuffers.Count(); - -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - const auto fence = _backBuffers[_semaphoreIndex].ImageAcquiredFence; - _device->FenceManager.ResetFence(fence); -#endif - const auto semaphore = _backBuffers[_semaphoreIndex].ImageAcquiredSemaphore; const VkResult result = vkAcquireNextImageKHR( @@ -529,11 +513,7 @@ int32 GPUSwapChainVulkan::AcquireImageIndex(SemaphoreVulkan** outSemaphore) _swapChain, UINT64_MAX, semaphore->GetHandle(), -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - fence->GetHandle(), -#else VK_NULL_HANDLE, -#endif &imageIndex); if (result == VK_ERROR_OUT_OF_DATE_KHR) @@ -562,10 +542,6 @@ int32 GPUSwapChainVulkan::AcquireImageIndex(SemaphoreVulkan** outSemaphore) } _currentImageIndex = (int32)imageIndex; -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - ASSERT(_device->FenceManager.WaitForFence(fence, UINT64_MAX)); -#endif - return _currentImageIndex; } diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.h index 93ff126d9..36204581c 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.h @@ -30,15 +30,6 @@ public: /// SemaphoreVulkan* RenderingDoneSemaphore; -#if VULKAN_USE_IMAGE_ACQUIRE_FENCES - - /// - /// The image acquired fence handle. - /// - FenceVulkan* ImageAcquiredFence; - -#endif - /// /// The render target surface handle. /// diff --git a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h index 66e5a608d..070d3a9c9 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h @@ -8,7 +8,6 @@ #define VULKAN_USE_DEBUG_LAYER GPU_ENABLE_DIAGNOSTICS #define VULKAN_HAS_PHYSICAL_DEVICE_PROPERTIES2 1 -#define VULKAN_ENABLE_DESKTOP_HMD_SUPPORT 0 /// /// The implementation for the Vulkan API support for Linux platform. diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h index 02dd2c68d..c0c45b636 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h @@ -78,40 +78,32 @@ public: case 0: stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; break; - case VK_ACCESS_TRANSFER_WRITE_BIT: stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; break; - case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; - case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; - + case VK_ACCESS_TRANSFER_READ_BIT: + stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_ACCESS_SHADER_READ_BIT: + case VK_ACCESS_SHADER_WRITE_BIT: + stageFlags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; #if VULKAN_SUPPORTS_MAINTENANCE_LAYER2 case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; #endif - - case VK_ACCESS_TRANSFER_READ_BIT: - stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - - case VK_ACCESS_SHADER_READ_BIT: - case VK_ACCESS_SHADER_WRITE_BIT: - stageFlags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - default: CRASH; break; } - return stageFlags; } @@ -136,12 +128,6 @@ public: accessFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; -#if VULKAN_SUPPORTS_MAINTENANCE_LAYER2 - case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR: - accessFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - break; -#endif case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: accessFlags = VK_ACCESS_TRANSFER_READ_BIT; stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; @@ -158,6 +144,12 @@ public: accessFlags = VK_ACCESS_SHADER_READ_BIT; stageFlags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; +#if VULKAN_SUPPORTS_MAINTENANCE_LAYER2 + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR: + accessFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + break; +#endif case VK_IMAGE_LAYOUT_GENERAL: accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; stageFlags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; From 760d5869232b517b306e9b7a26ef6ede484e6bc7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 11:18:00 +0100 Subject: [PATCH 03/11] Fix crash when using Physical Material with missing instance (cherry picked from commit 5e77925492addb7c226d9db2758288b3918c429d) --- Source/Engine/Physics/Colliders/Collider.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp index b00ceb925..9ddc4f1bc 100644 --- a/Source/Engine/Physics/Colliders/Collider.cpp +++ b/Source/Engine/Physics/Colliders/Collider.cpp @@ -207,7 +207,7 @@ void Collider::Attach(RigidBody* rigidBody) // Attach rigidBody->GetPhysXRigidActor()->attachShape(*_shape); - _shape->setLocalPose(PxTransform(C2P((_localTransform.Translation + _localTransform.Orientation * _center) * rigidBody->GetScale()), C2P(_localTransform.Orientation))); + _shape->setLocalPose(PxTransform(C2P((_localTransform.Translation + _localTransform.Orientation * _center) * rigidBody->GetScale()), C2P(_localTransform.Orientation))); if (rigidBody->IsDuringPlay()) rigidBody->UpdateBounds(); } @@ -246,7 +246,7 @@ void Collider::CreateShapeBase(const PxGeometry& geometry) const bool isTrigger = _isTrigger && CanBeTrigger(); const PxShapeFlags shapeFlags = GetShapeFlags(isTrigger, IsActiveInHierarchy()); PxMaterial* material = Physics::GetDefaultMaterial(); - if (Material && !Material->WaitForLoaded()) + if (Material && !Material->WaitForLoaded() && Material->Instance) { material = ((PhysicalMaterial*)Material->Instance)->GetPhysXMaterial(); } @@ -291,12 +291,9 @@ void Collider::OnMaterialChanged() if (_shape) { PxMaterial* material = Physics::GetDefaultMaterial(); - if (Material) + if (Material && !Material->WaitForLoaded() && Material->Instance) { - if (!Material->WaitForLoaded()) - { - material = ((PhysicalMaterial*)Material->Instance)->GetPhysXMaterial(); - } + material = ((PhysicalMaterial*)Material->Instance)->GetPhysXMaterial(); } _shape->setMaterials(&material, 1); } From 4fe91d57b7964d9efa960677b7081fe4f270b962 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 13:45:02 +0100 Subject: [PATCH 04/11] Fix code style --- Content/Shaders/ColorGrading.flax | 4 +- Content/Shaders/DepthOfField.flax | 4 +- Content/Shaders/Fog.flax | 4 +- Content/Shaders/ProbesFilter.flax | 4 +- Content/Shaders/VolumetricFog.flax | 4 +- Source/Shaders/BRDF.hlsl | 16 +- Source/Shaders/ColorGrading.shader | 34 ++-- Source/Shaders/DepthOfField.shader | 10 +- Source/Shaders/ExponentialHeightFog.hlsl | 44 +++--- Source/Shaders/Fog.shader | 18 +-- Source/Shaders/ProbesFilter.shader | 2 +- Source/Shaders/VolumetricFog.shader | 189 ++++++++++------------- 12 files changed, 151 insertions(+), 182 deletions(-) diff --git a/Content/Shaders/ColorGrading.flax b/Content/Shaders/ColorGrading.flax index eef24db35..b89d4b22b 100644 --- a/Content/Shaders/ColorGrading.flax +++ b/Content/Shaders/ColorGrading.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e25c173644fa6e459791e1222514b77d71847bcc1d063accbf5e94e16d83527f -size 11057 +oid sha256:ae31d654f71cd691f66cd140fd066ad2cf8a31d984f62f411173972471b9022b +size 10987 diff --git a/Content/Shaders/DepthOfField.flax b/Content/Shaders/DepthOfField.flax index 5acc84c3e..a0831c322 100644 --- a/Content/Shaders/DepthOfField.flax +++ b/Content/Shaders/DepthOfField.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4fe6201d9c205835e9a16f05fd3e95400854ea162bce8b1473037e52c7cfd69 -size 21043 +oid sha256:bea89bc4545dd7268448f3a66b7176801759744eb1f625e8c036fdd064fa4cfe +size 21025 diff --git a/Content/Shaders/Fog.flax b/Content/Shaders/Fog.flax index 126388165..f3376447a 100644 --- a/Content/Shaders/Fog.flax +++ b/Content/Shaders/Fog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17bb8171cdafe227429d694733060a5ce7c647a48da9d6f4215f336ada03dc56 -size 2943 +oid sha256:574afd4d29bf42d17dfbc3da1b9841c1bfac8e8f4f05ff2b1ca9658eb5b8d159 +size 2878 diff --git a/Content/Shaders/ProbesFilter.flax b/Content/Shaders/ProbesFilter.flax index c95b5aac3..91fe4a08b 100644 --- a/Content/Shaders/ProbesFilter.flax +++ b/Content/Shaders/ProbesFilter.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24e0095be6046f8cd05ed79f25c6b90b8c257420b686e050fdcedb6b210d963c -size 4999 +oid sha256:78d5d554e4dc59fdb9bcfef7c4ad0ee96cebb79b67e3e443a5a580e4e664135a +size 4980 diff --git a/Content/Shaders/VolumetricFog.flax b/Content/Shaders/VolumetricFog.flax index e62d7f4c1..4cd23cb0c 100644 --- a/Content/Shaders/VolumetricFog.flax +++ b/Content/Shaders/VolumetricFog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:daa92cd2b9f3dbc55923cf92561d6d91ab8f5d14dec183f418e03932d09f26b3 -size 15820 +oid sha256:6e278259855304359f5cf5d4860c5d473eaae4ae20cdfe73a8b311fdfc00b1aa +size 14492 diff --git a/Source/Shaders/BRDF.hlsl b/Source/Shaders/BRDF.hlsl index 4b1f0389a..47a641b16 100644 --- a/Source/Shaders/BRDF.hlsl +++ b/Source/Shaders/BRDF.hlsl @@ -25,9 +25,9 @@ float D_GGX(float roughness, float NoH) float Vis_Schlick(float roughness, float NoV, float NoL) { float k = Square(roughness) * 0.5; - float vis_SchlickV = NoV * (1 - k) + k; - float vis_SchlickL = NoL * (1 - k) + k; - return 0.25 / (vis_SchlickV * vis_SchlickL); + float visSchlickV = NoV * (1 - k) + k; + float visSchlickL = NoL * (1 - k) + k; + return 0.25 / (visSchlickV * visSchlickL); } // Smith term for GGX @@ -36,9 +36,9 @@ float Vis_Smith(float roughness, float NoV, float NoL) { float a = Square(roughness); float a2 = a * a; - float vis_SmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2); - float vis_SmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2); - return rcp(vis_SmithV * vis_SmithL); + float visSmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2); + float visSmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2); + return rcp(visSmithV * visSmithL); } // Appoximation of joint Smith term for GGX @@ -74,7 +74,7 @@ half SSRMipFromRoughness(half roughness) return max(1, 10 - mip1px); } -float ComputeReflectionCaptureRoughnessFromMip(float mip) +float ProbeRoughnessFromMip(float mip) { float mip1px = REFLECTION_CAPTURE_NUM_MIPS - 1 - mip; return exp2((REFLECTION_CAPTURE_ROUGHEST_MIP - mip1px) / REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE); @@ -99,8 +99,6 @@ float3 EnvBRDF(Texture2D preIntegratedGF, float3 specularColor, float roughness, return specularColor * ab.x + saturate(50.0 * specularColor.g) * ab.y; } -#define MAX_SPECULAR_POWER 10000000000.0f - float RoughnessToSpecularPower(float roughness) { return pow(2, 13 * (1 - roughness)); diff --git a/Source/Shaders/ColorGrading.shader b/Source/Shaders/ColorGrading.shader index 51015658c..9a811cb0b 100644 --- a/Source/Shaders/ColorGrading.shader +++ b/Source/Shaders/ColorGrading.shader @@ -264,37 +264,33 @@ META_VS(true, FEATURE_LEVEL_SM4) META_FLAG(VertexToGeometryShader) META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) -Quad_VS2GS VS_WriteToSlice(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_InstanceID) +Quad_VS2GS VS_WriteToSlice(float2 position : POSITION0, float2 texCoord : TEXCOORD0, uint layerIndex : SV_InstanceID) { Quad_VS2GS output; - - output.Vertex.Position = float4(Position, 0, 1); - output.Vertex.TexCoord = TexCoord; - output.LayerIndex = LayerIndex; - + output.Vertex.Position = float4(position, 0, 1); + output.Vertex.TexCoord = texCoord; + output.LayerIndex = layerIndex; return output; } // Geometry shader that writes to a range of slices of a volume texture META_GS(true, FEATURE_LEVEL_SM4) [maxvertexcount(3)] -void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream OutStream) +void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream stream) { - Quad_GS2PS vertex0; - vertex0.Vertex = input[0].Vertex; - vertex0.LayerIndex = input[0].LayerIndex; + Quad_GS2PS vertex; - Quad_GS2PS vertex1; - vertex1.Vertex = input[1].Vertex; - vertex1.LayerIndex = input[1].LayerIndex; + vertex.Vertex = input[0].Vertex; + vertex.LayerIndex = input[0].LayerIndex; + stream.Append(vertex); - Quad_GS2PS vertex2; - vertex2.Vertex = input[2].Vertex; - vertex2.LayerIndex = input[2].LayerIndex; + vertex.Vertex = input[1].Vertex; + vertex.LayerIndex = input[1].LayerIndex; + stream.Append(vertex); - OutStream.Append(vertex0); - OutStream.Append(vertex1); - OutStream.Append(vertex2); + vertex.Vertex = input[2].Vertex; + vertex.LayerIndex = input[2].LayerIndex; + stream.Append(vertex); } META_PS(true, FEATURE_LEVEL_ES2) diff --git a/Source/Shaders/DepthOfField.shader b/Source/Shaders/DepthOfField.shader index 1855e728c..062f17c5b 100644 --- a/Source/Shaders/DepthOfField.shader +++ b/Source/Shaders/DepthOfField.shader @@ -571,9 +571,9 @@ StructuredBuffer BokehPointBuffer : register(t2); // Vertex Shader, positions and scales the bokeh point META_VS(true, FEATURE_LEVEL_SM5) META_FLAG(VertexToGeometryShader) -BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID) +BokehVSOutput VS_Bokeh(in uint vertexID : SV_VertexID) { - BokehPoint bPoint = BokehPointBuffer[VertexID]; + BokehPoint bPoint = BokehPointBuffer[vertexID]; BokehVSOutput output; // Position the vertex in normalized device coordinate space [-1, 1] @@ -599,7 +599,7 @@ BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID) // Geometry Shader, expands a vertex into a quad with two triangles META_GS(true, FEATURE_LEVEL_SM5) [maxvertexcount(4)] -void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream SpriteStream) +void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream stream) { BokehGSOutput output; @@ -613,9 +613,9 @@ void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream output.Color = input[0].Color; output.Depth = input[0].Depth; - SpriteStream.Append(output); + stream.Append(output); } - SpriteStream.RestartStrip(); + stream.RestartStrip(); } // Pixel Shader, applies the bokeh shape texture diff --git a/Source/Shaders/ExponentialHeightFog.hlsl b/Source/Shaders/ExponentialHeightFog.hlsl index cf085d7fe..9727380f1 100644 --- a/Source/Shaders/ExponentialHeightFog.hlsl +++ b/Source/Shaders/ExponentialHeightFog.hlsl @@ -29,29 +29,29 @@ struct ExponentialHeightFogData float StartDistance; }; -half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 worldPosition, float3 cameraPosition, float excludeDistance) +float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance) { - float3 cameraToReceiver = worldPosition - cameraPosition; - float cameraToReceiverLengthSqr = dot(cameraToReceiver, cameraToReceiver); - float cameraToReceiverLengthInv = rsqrt(cameraToReceiverLengthSqr); - float cameraToReceiverLength = cameraToReceiverLengthSqr * cameraToReceiverLengthInv; - half3 cameraToReceiverNormalized = cameraToReceiver * cameraToReceiverLengthInv; + float3 cameraToPos = posWS - camWS; + float cameraToPosSqr = dot(cameraToPos, cameraToPos); + float cameraToPosLenInv = rsqrt(cameraToPosSqr); + float cameraToPosLen = cameraToPosSqr * cameraToPosLenInv; + float3 cameraToReceiverNorm = cameraToPos * cameraToPosLenInv; float rayOriginTerms = exponentialHeightFog.FogAtViewPosition; - float rayLength = cameraToReceiverLength; - float rayDirectionY = cameraToReceiver.y; + float rayLength = cameraToPosLen; + float rayDirectionY = cameraToPos.y; // Apply start distance offset - excludeDistance = max(excludeDistance, exponentialHeightFog.StartDistance); - if (excludeDistance > 0) + skipDistance = max(skipDistance, exponentialHeightFog.StartDistance); + if (skipDistance > 0) { - float excludeIntersectionTime = excludeDistance * cameraToReceiverLengthInv; - float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToReceiver.y; - float exclusionIntersectionY = cameraPosition.y + cameraToExclusionIntersectionY; - float exclusionIntersectionToReceiverY = cameraToReceiver.y - cameraToExclusionIntersectionY; + float excludeIntersectionTime = skipDistance * cameraToPosLenInv; + float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToPos.y; + float exclusionIntersectionY = camWS.y + cameraToExclusionIntersectionY; + float exclusionIntersectionToReceiverY = cameraToPos.y - cameraToExclusionIntersectionY; // Calculate fog off of the ray starting from the exclusion distance, instead of starting from the camera - rayLength = (1.0f - excludeIntersectionTime) * cameraToReceiverLength; + rayLength = (1.0f - excludeIntersectionTime) * cameraToPosLen; rayDirectionY = exclusionIntersectionToReceiverY; // Move off the viewer @@ -67,22 +67,22 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo float exponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * rayLength; // Calculate the amount of light that made it through the fog using the transmission equation - half expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity); + float expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity); // Calculate the directional light inscattering - half3 inscatteringColor = exponentialHeightFog.FogInscatteringColor; - half3 directionalInscattering = 0; + float3 inscatteringColor = exponentialHeightFog.FogInscatteringColor; + float3 directionalInscattering = 0; BRANCH if (exponentialHeightFog.ApplyDirectionalInscattering > 0) { // Setup a cosine lobe around the light direction to approximate inscattering from the directional light off of the ambient haze - half3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNormalized, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent); + float3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNorm, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent); // Calculate the line integral of the eye ray through the haze, using a special starting distance to limit the inscattering to the distance float dirExponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * max(rayLength - exponentialHeightFog.DirectionalInscatteringStartDistance, 0.0f); // Calculate the amount of light that made it through the fog using the transmission equation - half directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral)); + float directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral)); // Final inscattering from the light directionalInscattering = directionalLightInscattering * (1 - directionalInscatteringFogFactor); @@ -90,13 +90,13 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo // Disable fog after a certain distance FLATTEN - if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToReceiverLength > exponentialHeightFog.FogCutoffDistance) + if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToPosLen > exponentialHeightFog.FogCutoffDistance) { expFogFactor = 1; directionalInscattering = 0; } - return half4((inscatteringColor) * (1 - expFogFactor) + directionalInscattering, expFogFactor); + return float4(inscatteringColor * (1.0f - expFogFactor) + directionalInscattering, expFogFactor); } #endif diff --git a/Source/Shaders/Fog.shader b/Source/Shaders/Fog.shader index 7ddfe88ae..93bcac24f 100644 --- a/Source/Shaders/Fog.shader +++ b/Source/Shaders/Fog.shader @@ -33,15 +33,15 @@ float3 GetWorldPos(float2 uv) return mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz; } -float4 CalculateCombinedFog(float3 worldPosition, float sceneDepth, float3 volumeUV) +float4 CalculateCombinedFog(float3 posWS, float sceneDepth, float3 volumeUV) { - float excludeDistance = 0; + float skipDistance = 0; #if VOLUMETRIC_FOG - excludeDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0); + skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0); #endif - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, worldPosition, GBuffer.ViewPos, excludeDistance); + float4 fog = GetExponentialHeightFog(ExponentialHeightFog, posWS, GBuffer.ViewPos, skipDistance); #if VOLUMETRIC_FOG float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0); @@ -57,8 +57,8 @@ META_PERMUTATION_1(VOLUMETRIC_FOG=1) float4 PS_Fog(Quad_VS2PS input) : SV_Target0 { // Calculate pixel world space position - float3 worldPosition = GetWorldPos(input.TexCoord); - float3 viewVector = worldPosition - GBuffer.ViewPos; + float3 posWS = GetWorldPos(input.TexCoord); + float3 viewVector = posWS - GBuffer.ViewPos; float sceneDepth = length(viewVector); // Calculate volumetric fog coordinates @@ -67,17 +67,17 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0 // Debug code #if VOLUMETRIC_FOG && 0 - volumeUV = worldPosition / 1000; + volumeUV = posWS / 1000; if (!all(volumeUV >= 0 && volumeUV <= 1)) return 0; return float4(IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0).rgb, 1); //return float4(volumeUV, 1); - //return float4(worldPosition / 100, 1); + //return float4(posWS / 100, 1); #endif // Calculate fog color - float4 fog = CalculateCombinedFog(worldPosition, sceneDepth, volumeUV); + float4 fog = CalculateCombinedFog(posWS, sceneDepth, volumeUV); return fog; } diff --git a/Source/Shaders/ProbesFilter.shader b/Source/Shaders/ProbesFilter.shader index 8ff0f8536..b8daca0db 100644 --- a/Source/Shaders/ProbesFilter.shader +++ b/Source/Shaders/ProbesFilter.shader @@ -65,7 +65,7 @@ float4 PS_FilterFace(Quad_VS2PS input) : SV_Target #define NUM_FILTER_SAMPLES 512 float3 N = normalize(cubeCoordinates); - float roughness = ComputeReflectionCaptureRoughnessFromMip(SourceMipIndex); + float roughness = ProbeRoughnessFromMip(SourceMipIndex); float4 filteredColor = 0; float weight = 0; diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index cc07de293..0b1fdb650 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -61,7 +61,7 @@ META_CB_END META_CB_BEGIN(1, PerLight) float2 Dummy1; -int MinZ; // Z index of the minimum slice in the range +int MinZ; float LocalLightScatteringIntensity; float4 ViewSpaceBoundingSphere; @@ -72,48 +72,44 @@ LightShadowData LocalLightShadow; META_CB_END -float ComputeDepthFromZSlice(float zSlice) -{ - return (zSlice / GridSize.z) * VolumetricFogMaxDistance; -} - -float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth) -{ - float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy; - sceneDepth = ComputeDepthFromZSlice(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar; - float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth); - return GetWorldPos(GBuffer, volumeUV, deviceDepth); -} - -float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset) -{ - float unused; - return ComputeCellWorldPosition(gridCoordinate, cellOffset, unused); -} - -float ComputeNormalizedZSliceFromDepth(float sceneDepth) -{ - return sceneDepth / VolumetricFogMaxDistance; -} - -float3 ComputeVolumeUV(float3 worldPosition, float4x4 worldToClip) -{ - float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip); - ndcPosition.xy /= ndcPosition.w; - return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ComputeNormalizedZSliceFromDepth(ndcPosition.w)); -} - +// The Henyey-Greenstein phase function +// [Henyey and Greenstein 1941, https://www.astro.umd.edu/~jph/HG_note.pdf] float HenyeyGreensteinPhase(float g, float cosTheta) { return (1 - g * g) / (4 * PI * pow(1 + g * g + 2 * g * cosTheta, 1.5f)); } -// +g = forward scattering, 0=g = isotropic, -g = backward scattering -float PhaseFunction(float g, float cosTheta) +float GetPhase(float g, float cosTheta) { return HenyeyGreensteinPhase(g, cosTheta); } +float GetSliceDepth(float zSlice) +{ + return (zSlice / GridSize.z) * VolumetricFogMaxDistance; +} + +float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth) +{ + float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy; + sceneDepth = GetSliceDepth(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar; + float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth); + return GetWorldPos(GBuffer, volumeUV, deviceDepth); +} + +float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset) +{ + float temp; + return GetCellPositionWS(gridCoordinate, cellOffset, temp); +} + +float3 GetVolumeUV(float3 worldPosition, float4x4 worldToClip) +{ + float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip); + ndcPosition.xy /= ndcPosition.w; + return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ndcPosition.w / VolumetricFogMaxDistance); +} + // Vertex shader that writes to a range of slices of a volume texture META_VS(true, FEATURE_LEVEL_SM5) META_FLAG(VertexToGeometryShader) @@ -123,22 +119,18 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins Quad_VS2GS output; uint slice = LayerIndex + MinZ; - float sliceDepth = ComputeDepthFromZSlice(slice); - float sliceDepthOffset = abs(sliceDepth - ViewSpaceBoundingSphere.z); + float depth = GetSliceDepth(slice); + float depthOffset = abs(depth - ViewSpaceBoundingSphere.z); - if (sliceDepthOffset < ViewSpaceBoundingSphere.w) + if (depthOffset < ViewSpaceBoundingSphere.w) { - // Compute the radius of the circle formed by the intersection of the bounding sphere and the current depth slice - float sliceRadius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - sliceDepthOffset * sliceDepthOffset); - - // Place the quad vertex to tightly bound the circle - float3 viewSpaceVertexPosition = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * sliceRadius, sliceDepth); - output.Vertex.Position = mul(float4(viewSpaceVertexPosition, 1), ViewToVolumeClip); + float radius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - depthOffset * depthOffset); + float3 positionVS = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * radius, depth); + output.Vertex.Position = mul(float4(positionVS, 1), ViewToVolumeClip); } else { - // Slice does not intersect bounding sphere, emit degenerate triangle - output.Vertex.Position = 0; + output.Vertex.Position = float4(0, 0, 0, 0); } output.Vertex.TexCoord = 0; @@ -150,23 +142,21 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins // Geometry shader that writes to a range of slices of a volume texture META_GS(true, FEATURE_LEVEL_SM5) [maxvertexcount(3)] -void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream OutStream) +void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream stream) { - Quad_GS2PS vertex0; - vertex0.Vertex = input[0].Vertex; - vertex0.LayerIndex = input[0].LayerIndex; + Quad_GS2PS vertex; - Quad_GS2PS vertex1; - vertex1.Vertex = input[1].Vertex; - vertex1.LayerIndex = input[1].LayerIndex; + vertex.Vertex = input[0].Vertex; + vertex.LayerIndex = input[0].LayerIndex; + stream.Append(vertex); - Quad_GS2PS vertex2; - vertex2.Vertex = input[2].Vertex; - vertex2.LayerIndex = input[2].LayerIndex; + vertex.Vertex = input[1].Vertex; + vertex.LayerIndex = input[1].LayerIndex; + stream.Append(vertex); - OutStream.Append(vertex0); - OutStream.Append(vertex1); - OutStream.Append(vertex2); + vertex.Vertex = input[2].Vertex; + vertex.LayerIndex = input[2].LayerIndex; + stream.Append(vertex); } #if USE_SHADOW @@ -208,18 +198,16 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 return 0; #if USE_TEMPORAL_REPROJECTION - float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip); + float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip); float historyAlpha = HistoryWeight; - FLATTEN if (any(historyUV < 0) || any(historyUV > 1)) { historyAlpha = 0; } - - uint numSuperSamples = historyAlpha < .001f ? HistoryMissSuperSampleCount : 1; + uint samplesCount = historyAlpha < 0.001f ? HistoryMissSuperSampleCount : 1; #else - uint numSuperSamples = 1; + uint samplesCount = 1; #endif float3 L = 0; @@ -229,22 +217,19 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 float lightRadiusMask = 1; float spotAttenuation = 1; bool isSpotLight = LocalLight.SpotAngles.x > -2.0f; - float4 scattering = 0; - for (uint sampleIndex = 0; sampleIndex < numSuperSamples; sampleIndex++) + for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) { float3 cellOffset = FrameJitterOffsets[sampleIndex].xyz; //float cellOffset = 0.5f; - float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset); - float3 cameraVector = normalize(worldPosition - GBuffer.ViewPos); - float cellRadius = length(worldPosition - ComputeCellWorldPosition(gridCoordinate + uint3(1, 1, 1), cellOffset)); - - // Bias the inverse squared light falloff based on voxel size to prevent aliasing near the light source + float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset); + float3 cameraVector = normalize(positionWS - GBuffer.ViewPos); + float cellRadius = length(positionWS - GetCellPositionWS(gridCoordinate + uint3(1, 1, 1), cellOffset)); float distanceBias = max(cellRadius * InverseSquaredLightDistanceBiasScale, 1); - // Get the light attenuation - GetRadialLightAttenuation(LocalLight, isSpotLight, worldPosition, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation); + // Calculate the light attenuation + GetRadialLightAttenuation(LocalLight, isSpotLight, positionWS, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation); float combinedAttenuation = distanceAttenuation * lightRadiusMask * spotAttenuation; // Peek the shadow @@ -252,16 +237,14 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 #if USE_SHADOW if (combinedAttenuation > 0) { - shadowFactor = ComputeVolumeShadowing(worldPosition, isSpotLight); + shadowFactor = ComputeVolumeShadowing(positionWS, isSpotLight); } #endif - scattering.rgb += LocalLight.Color * (PhaseFunction(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity); + scattering.rgb += LocalLight.Color * (GetPhase(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity); } - // Normalize - scattering.rgb /= (float)numSuperSamples; - + scattering.rgb /= (float)samplesCount; return scattering; } @@ -280,7 +263,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa // Center of the voxel float voxelOffset = 0.5f; - float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, voxelOffset); + float3 positionWS = GetCellPositionWS(gridCoordinate, voxelOffset); // Unpack the fog parameters (packing done in C++ ExponentialHeightFog::GetVolumetricFogOptions) float fogDensity = FogParameters.x; @@ -288,7 +271,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa float fogHeightFalloff = FogParameters.z; // Calculate the global fog density that matches the exponential height fog density - float globalDensity = fogDensity * exp2(-fogHeightFalloff * (worldPosition.y - fogHeight)); + float globalDensity = fogDensity * exp2(-fogHeightFalloff * (positionWS.y - fogHeight)); float matchFactor = 0.24f; float extinction = max(globalDensity * GlobalExtinctionScale * matchFactor, 0); @@ -326,7 +309,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ uint numSuperSamples = 1; #if USE_TEMPORAL_REPROJECTION - float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip); + float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip); float historyAlpha = HistoryWeight; // Discard history if it lays outside the current view @@ -347,8 +330,8 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ //float3 cellOffset = 0.5f; float sceneDepth; - float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset, sceneDepth); - float3 cameraVector = worldPosition - GBuffer.ViewPos; + float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset, sceneDepth); + float3 cameraVector = positionWS - GBuffer.ViewPos; float cameraVectorLength = length(cameraVector); float3 cameraVectorNormalized = cameraVector / cameraVectorLength; @@ -360,10 +343,10 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ float shadow = 1; if (DirectionalLightShadow.NumCascades > 0) { - shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, worldPosition, cameraVectorLength); + shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, positionWS, cameraVectorLength); } - lightScattering += DirectionalLight.Color * (8 * shadow * PhaseFunction(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized))); + lightScattering += DirectionalLight.Color * (8 * shadow * GetPhase(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized))); } // Sky light @@ -414,38 +397,30 @@ META_CS(true, FEATURE_LEVEL_SM5) void CS_FinalIntegration(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint3 GroupThreadId : SV_GroupThreadID) { uint3 gridCoordinate = DispatchThreadId; - - float4 accumulatedLightingAndTransmittance = float4(0, 0, 0, 1); - float3 previousSliceWorldPosition = GBuffer.ViewPos; + float4 acc = float4(0, 0, 0, 1); + float3 prevPositionWS = GBuffer.ViewPos; for (uint layerIndex = 0; layerIndex < GridSizeInt.z; layerIndex++) { - uint3 layerCoordinate = uint3(gridCoordinate.xy, layerIndex); - float4 scatteringAndExtinction = LightScattering[layerCoordinate]; - - float3 layerWorldPosition = ComputeCellWorldPosition(layerCoordinate, 0.5f); - float stepLength = length(layerWorldPosition - previousSliceWorldPosition); - previousSliceWorldPosition = layerWorldPosition; - - float transmittance = exp(-scatteringAndExtinction.w * stepLength); + uint3 coords = uint3(gridCoordinate.xy, layerIndex); + float4 scatteringExtinction = LightScattering[coords]; + float3 positionWS = GetCellPositionWS(coords, 0.5f); // Ref: "Physically Based and Unified Volumetric Rendering in Frostbite" -#define ENERGY_CONSERVING_INTEGRATION 1 -#if ENERGY_CONSERVING_INTEGRATION - float3 scatteringIntegratedOverSlice = (scatteringAndExtinction.rgb - scatteringAndExtinction.rgb * transmittance) / max(scatteringAndExtinction.w, .00001f); - accumulatedLightingAndTransmittance.rgb += scatteringIntegratedOverSlice * accumulatedLightingAndTransmittance.a; -#else - accumulatedLightingAndTransmittance.rgb += scatteringAndExtinction.rgb * accumulatedLightingAndTransmittance.a; -#endif - accumulatedLightingAndTransmittance.a *= transmittance; - + float transmittance = exp(-scatteringExtinction.w * length(positionWS - prevPositionWS)); + float3 scatteringIntegratedOverSlice = (scatteringExtinction.rgb - scatteringExtinction.rgb * transmittance) / max(scatteringExtinction.w, 0.00001f); + acc.rgb += scatteringIntegratedOverSlice * acc.a; + acc.a *= transmittance; + #if DEBUG_VOXELS - RWIntegratedLightScattering[layerCoordinate] = float4(scatteringAndExtinction.rgb, 1.0f); + RWIntegratedLightScattering[coords] = float4(scatteringExtinction.rgb, 1.0f); #elif DEBUG_VOXEL_WS_POS - RWIntegratedLightScattering[layerCoordinate] = float4(layerWorldPosition.rgb, 1.0f); + RWIntegratedLightScattering[coords] = float4(positionWS.rgb, 1.0f); #else - RWIntegratedLightScattering[layerCoordinate] = accumulatedLightingAndTransmittance; + RWIntegratedLightScattering[coords] = acc; #endif + + prevPositionWS = positionWS; } } From cf0aeb79bff47e8a56a76930b4805ccd436e8d76 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 18:07:53 +0100 Subject: [PATCH 05/11] Remove TAA and Motion Blur implementations --- Content/Shaders/MotionBlur.flax | 4 +- Content/Shaders/TAA.flax | 4 +- Source/Engine/Renderer/AntiAliasing/TAA.cpp | 54 +--- Source/Engine/Renderer/AntiAliasing/TAA.h | 11 +- Source/Engine/Renderer/MotionBlurPass.cpp | 246 +------------- Source/Engine/Renderer/MotionBlurPass.h | 43 +-- Source/Engine/Renderer/Renderer.cpp | 4 +- Source/Shaders/MotionBlur.shader | 342 -------------------- Source/Shaders/TAA.shader | 145 +-------- 9 files changed, 26 insertions(+), 827 deletions(-) diff --git a/Content/Shaders/MotionBlur.flax b/Content/Shaders/MotionBlur.flax index 5da5d5bff..2f93589f0 100644 --- a/Content/Shaders/MotionBlur.flax +++ b/Content/Shaders/MotionBlur.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46132e260d5f8b92e81760685903ea8fcfb2e13cca234076046b838a7f904b43 -size 13051 +oid sha256:1bb224fc630264fcfa58c6d8ce27759e44d3f989a53655dc35959e594890d146 +size 1838 diff --git a/Content/Shaders/TAA.flax b/Content/Shaders/TAA.flax index 8f4291616..17564fda3 100644 --- a/Content/Shaders/TAA.flax +++ b/Content/Shaders/TAA.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee25f1de47f9d513463871c90af63fb9895118813dd6d4f96b367b2c6685258e -size 5120 +oid sha256:83d415b15679c8203b8db16d9b7ef99a74aa8e07ba2753109d6d3e4eeba2cece +size 712 diff --git a/Source/Engine/Renderer/AntiAliasing/TAA.cpp b/Source/Engine/Renderer/AntiAliasing/TAA.cpp index d8d0f3e75..3c479f74e 100644 --- a/Source/Engine/Renderer/AntiAliasing/TAA.cpp +++ b/Source/Engine/Renderer/AntiAliasing/TAA.cpp @@ -12,7 +12,7 @@ bool TAA::Init() { // Create pipeline state - _psTAA.CreatePipelineStates(); + //_psTAA.CreatePipelineStates(); // Load shader _shader = Content::LoadAsyncInternal(TEXT("Shaders/TAA")); @@ -34,22 +34,6 @@ bool TAA::setupResources() } const auto shader = _shader->GetShader(); - // Validate shader constant buffer size - if (shader->GetCB(0)->GetSize() != sizeof(Data)) - { - REPORT_INVALID_SHADER_PASS_CB_SIZE(shader, 0, Data); - return true; - } - - // Create pipeline state - GPUPipelineState::Description psDesc; - if (!_psTAA.IsValid()) - { - psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle; - if (_psTAA.Create(psDesc, shader, "PS")) - return true; - } - return false; } @@ -58,10 +42,7 @@ void TAA::Dispose() // Base RendererPass::Dispose(); - // Delete pipeline state - _psTAA.Delete(); - - // Release asset + _psTAA = nullptr; _shader.Unlink(); } @@ -75,7 +56,7 @@ void TAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureView auto context = GPUDevice::Instance->GetMainContext(); // Ensure to have valid data - if (checkIfSkipPass()) + //if (checkIfSkipPass()) { // Resources are missing. Do not perform rendering, just copy source frame. context->SetRenderTarget(output); @@ -119,32 +100,5 @@ void TAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureView blendStrength = 0.0f; } - // Bind input - Data data; - data.ScreenSize = renderContext.View.ScreenSize; - data.TaaJitterStrength.X = renderContext.View.TemporalAAJitter.X; - data.TaaJitterStrength.Y = renderContext.View.TemporalAAJitter.Y; - data.TaaJitterStrength.Z = data.TaaJitterStrength.X / tempDesc.Width; - data.TaaJitterStrength.W = data.TaaJitterStrength.Y / tempDesc.Height; - data.FinalBlendParameters.X = settings.TAA_StationaryBlending * blendStrength; - data.FinalBlendParameters.Y = settings.TAA_MotionBlending * blendStrength; - data.FinalBlendParameters.Z = 100.0f * 60.0f; - data.FinalBlendParameters.W = settings.TAA_Sharpness; - const auto cb = _shader->GetShader()->GetCB(0); - context->UpdateCB(cb, &data); - context->BindCB(0, cb); - context->BindSR(0, input); - context->BindSR(1, inputHistory); - context->BindSR(2, renderContext.Buffers->MotionVectors); - context->BindSR(3, renderContext.Buffers->DepthBuffer); - - // Render - GPUTextureView* rts[] = { output, outputHistory->View() }; - context->SetRenderTarget(nullptr, ToSpan(rts, ARRAY_COUNT(rts))); - context->SetState(_psTAA.Get(renderContext.View.IsOrthographicProjection() ? 1 : 0)); - context->DrawFullscreenTriangle(); - - // Swap the history - RenderTargetPool::Release(inputHistory); - renderContext.Buffers->TemporalAA = outputHistory; + // ... } diff --git a/Source/Engine/Renderer/AntiAliasing/TAA.h b/Source/Engine/Renderer/AntiAliasing/TAA.h index 79fd0722c..074a64424 100644 --- a/Source/Engine/Renderer/AntiAliasing/TAA.h +++ b/Source/Engine/Renderer/AntiAliasing/TAA.h @@ -12,15 +12,8 @@ class TAA : public RendererPass { private: - PACK_STRUCT(struct Data - { - Vector4 ScreenSize; - Vector4 TaaJitterStrength; - Vector4 FinalBlendParameters; - }); - AssetReference _shader; - GPUPipelineStatePermutationsPs<2> _psTAA; + GPUPipelineState* _psTAA; public: @@ -44,7 +37,7 @@ private: #if COMPILE_WITH_DEV_ENV void OnShaderReloading(Asset* obj) { - _psTAA.Release(); + _psTAA = nullptr; invalidateResources(); } #endif diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp index 3d437e408..e6264ead6 100644 --- a/Source/Engine/Renderer/MotionBlurPass.cpp +++ b/Source/Engine/Renderer/MotionBlurPass.cpp @@ -11,19 +11,16 @@ #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Graphics/RenderBuffers.h" +PACK_STRUCT(struct Data { + GBufferData GBuffer; + Matrix CurrentVP; + Matrix PreviousVP; + Vector4 TemporalAAJitter; + }); + MotionBlurPass::MotionBlurPass() : _motionVectorsFormat(PixelFormat::Unknown) , _velocityFormat(PixelFormat::Unknown) - , _psCameraMotionVectors(nullptr) - , _psMotionVectorsDebug(nullptr) - , _psMotionVectorsDebugArrow(nullptr) - , _psVelocitySetup(nullptr) - , _psTileMax1(nullptr) - , _psTileMax2(nullptr) - , _psTileMax4(nullptr) - , _psTileMaxV(nullptr) - , _psNeighborMax(nullptr) - , _psReconstruction(nullptr) { } @@ -36,15 +33,6 @@ bool MotionBlurPass::Init() { // Create pipeline state _psCameraMotionVectors = GPUDevice::Instance->CreatePipelineState(); - _psMotionVectorsDebug = GPUDevice::Instance->CreatePipelineState(); - _psMotionVectorsDebugArrow = GPUDevice::Instance->CreatePipelineState(); - _psVelocitySetup = GPUDevice::Instance->CreatePipelineState(); - _psTileMax1 = GPUDevice::Instance->CreatePipelineState(); - _psTileMax2 = GPUDevice::Instance->CreatePipelineState(); - _psTileMax4 = GPUDevice::Instance->CreatePipelineState(); - _psTileMaxV = GPUDevice::Instance->CreatePipelineState(); - _psNeighborMax = GPUDevice::Instance->CreatePipelineState(); - _psReconstruction = GPUDevice::Instance->CreatePipelineState(); // Load shader _shader = Content::LoadAsyncInternal(TEXT("Shaders/MotionBlur")); @@ -98,62 +86,6 @@ bool MotionBlurPass::setupResources() if (_psCameraMotionVectors->Init(psDesc)) return true; } - if (!_psVelocitySetup->IsValid()) - { - psDesc.PS = shader->GetPS("PS_VelocitySetup"); - if (_psVelocitySetup->Init(psDesc)) - return true; - } - if (!_psTileMax1->IsValid()) - { - psDesc.PS = shader->GetPS("PS_TileMax1"); - if (_psTileMax1->Init(psDesc)) - return true; - } - if (!_psTileMax2->IsValid()) - { - psDesc.PS = shader->GetPS("PS_TileMax2"); - if (_psTileMax2->Init(psDesc)) - return true; - } - if (!_psTileMax4->IsValid()) - { - psDesc.PS = shader->GetPS("PS_TileMax4"); - if (_psTileMax4->Init(psDesc)) - return true; - } - if (!_psTileMaxV->IsValid()) - { - psDesc.PS = shader->GetPS("PS_TileMaxV"); - if (_psTileMaxV->Init(psDesc)) - return true; - } - if (!_psNeighborMax->IsValid()) - { - psDesc.PS = shader->GetPS("PS_NeighborMax"); - if (_psNeighborMax->Init(psDesc)) - return true; - } - if (!_psReconstruction->IsValid()) - { - psDesc.PS = shader->GetPS("PS_Reconstruction"); - if (_psReconstruction->Init(psDesc)) - return true; - } - if (!_psMotionVectorsDebug->IsValid()) - { - psDesc.PS = shader->GetPS("PS_MotionVectorsDebug"); - if (_psMotionVectorsDebug->Init(psDesc)) - return true; - } - if (!_psMotionVectorsDebugArrow->IsValid()) - { - psDesc.PrimitiveTopologyType = PrimitiveTopologyType::Line; - psDesc.VS = shader->GetVS("VS_DebugArrow"); - psDesc.PS = shader->GetPS("PS_DebugArrow"); - if (_psMotionVectorsDebugArrow->Init(psDesc)) - return true; - } return false; } @@ -165,15 +97,6 @@ void MotionBlurPass::Dispose() // Delete pipeline state SAFE_DELETE_GPU_RESOURCE(_psCameraMotionVectors); - SAFE_DELETE_GPU_RESOURCE(_psMotionVectorsDebug); - SAFE_DELETE_GPU_RESOURCE(_psMotionVectorsDebugArrow); - SAFE_DELETE_GPU_RESOURCE(_psVelocitySetup); - SAFE_DELETE_GPU_RESOURCE(_psTileMax1); - SAFE_DELETE_GPU_RESOURCE(_psTileMax2); - SAFE_DELETE_GPU_RESOURCE(_psTileMax4); - SAFE_DELETE_GPU_RESOURCE(_psTileMaxV); - SAFE_DELETE_GPU_RESOURCE(_psNeighborMax); - SAFE_DELETE_GPU_RESOURCE(_psReconstruction); // Release asset _shader.Unlink(); @@ -275,39 +198,13 @@ void MotionBlurPass::RenderDebug(RenderContext& renderContext, GPUTextureView* f { auto context = GPUDevice::Instance->GetMainContext(); const auto motionVectors = renderContext.Buffers->MotionVectors; - if (!motionVectors->IsAllocated() || setupResources()) + //if (!motionVectors->IsAllocated() || setupResources()) { context->Draw(frame); return; } - PROFILE_GPU_CPU("Motion Vectors Debug"); - - // Bind input - Data data; - GBufferPass::SetInputs(renderContext.View, data.GBuffer); - const float rows = 16.0f; - const float cols = rows * renderContext.Buffers->GetWidth() / renderContext.Buffers->GetHeight(); - data.DebugBlend = 0.7f; - data.DebugAmplitude = 2.0f; - data.DebugRowCount = static_cast(rows); - data.DebugColumnCount = static_cast(cols); - auto cb = _shader->GetShader()->GetCB(0); - context->UpdateCB(cb, &data); - context->BindCB(0, cb); - context->BindSR(0, frame); - context->BindSR(1, renderContext.Buffers->MotionVectors); - - // Draw motion gradient - context->SetState(_psMotionVectorsDebug); - context->DrawFullscreenTriangle(); - - // Draw arrows - context->SetState(_psMotionVectorsDebugArrow); - context->Draw(0, static_cast(cols * rows * 6)); - - // Cleanup - context->ResetSR(); + // .. } void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GPUTexture*& output) @@ -335,128 +232,5 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP return; } - // Need to have valid motion vectors created and rendered before - ASSERT(motionVectors->IsAllocated()); - - PROFILE_GPU_CPU("Motion Blur"); - - // Calculate the maximum blur radius in pixels - const float maxBlurRadius = 5.0f; - const int32 maxBlurPixels = static_cast(maxBlurRadius * motionVectorsHeight / 100.0f); - - // Calculate the TileMax size (it should be a multiple of 8 and larger than maxBlur) - const int32 tileSize = ((maxBlurPixels - 1) / 8 + 1) * 8; - - // Bind input - Data data; - GBufferPass::SetInputs(renderContext.View, data.GBuffer); - Matrix::Transpose(renderContext.View.ViewProjection(), data.CurrentVP); - Matrix::Transpose(renderContext.View.PrevViewProjection, data.PreviousVP); - data.TemporalAAJitter = renderContext.View.TemporalAAJitter; - data.VelocityScale = settings.Scale; - data.MaxBlurRadius = static_cast(maxBlurPixels); - data.RcpMaxBlurRadius = 1.0f / maxBlurPixels; - data.TileMaxOffs = Vector2::One * (tileSize / 8.0f - 1.0f) * -0.5f; - data.TileMaxLoop = static_cast(tileSize / 8.0f); - data.LoopCount = Math::Clamp(settings.SampleCount / 2.0f, 1.0f, 64.0f); - const float invWidth = 1.0f / motionVectorsWidth; - const float invHeight = 1.0f / motionVectorsHeight; - data.TexelSize1 = Vector2(invWidth, invHeight); - data.TexelSize2 = Vector2(invWidth * 2.0f, invHeight * 2.0f); - data.TexelSize4 = Vector2(invWidth * 4.0f, invHeight * 4.0f); - data.TexelSizeV = Vector2(invWidth * 8.0f, invHeight * 8.0f); - data.TexelSizeNM = Vector2(invWidth * tileSize, invHeight * tileSize); - data.MotionVectorsTexelSize = Vector2(1.0f / motionVectorsWidth, invHeight * tileSize); - auto cb = _shader->GetShader()->GetCB(0); - context->UpdateCB(cb, &data); - context->BindCB(0, cb); - context->BindSR(0, renderContext.Buffers->DepthBuffer); - auto rtDesc = GPUTextureDescription::New2D(motionVectorsWidth, motionVectorsHeight, _velocityFormat); - - // Pass 1 - Velocity/depth packing - auto vBuffer = RenderTargetPool::Get(rtDesc); - context->SetRenderTarget(*vBuffer); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, motionVectors->View()); - context->BindSR(1, renderContext.Buffers->DepthBuffer->View()); - context->SetState(_psVelocitySetup); - context->DrawFullscreenTriangle(); - context->UnBindSR(1); - - // Pass 2 - First TileMax filter (1/2 downsize) - rtDesc.Format = _motionVectorsFormat; - rtDesc.Width = motionVectorsWidth / 2; - rtDesc.Height = motionVectorsHeight / 2; - auto tile2 = RenderTargetPool::Get(rtDesc); - context->ResetRenderTarget(); - context->SetRenderTarget(tile2->View()); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, vBuffer->View()); - context->SetState(_psTileMax1); - context->DrawFullscreenTriangle(); - - // Pass 3 - Second TileMax filter (1/4 downsize) - rtDesc.Width = motionVectorsWidth / 4; - rtDesc.Height = motionVectorsHeight / 4; - auto tile4 = RenderTargetPool::Get(rtDesc); - context->ResetRenderTarget(); - context->SetRenderTarget(tile4->View()); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, tile2->View()); - context->SetState(_psTileMax2); - context->DrawFullscreenTriangle(); - RenderTargetPool::Release(tile2); - - // Pass 4 - Third TileMax filter (1/8 downsize) - rtDesc.Width = motionVectorsWidth / 8; - rtDesc.Height = motionVectorsHeight / 8; - auto tile8 = RenderTargetPool::Get(rtDesc); - context->ResetRenderTarget(); - context->SetRenderTarget(tile8->View()); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, tile4->View()); - context->SetState(_psTileMax4); - context->DrawFullscreenTriangle(); - RenderTargetPool::Release(tile4); - - // Pass 5 - Fourth TileMax filter (reduce to tileSize) - rtDesc.Width = motionVectorsWidth / tileSize; - rtDesc.Height = motionVectorsHeight / tileSize; - auto tile = RenderTargetPool::Get(rtDesc); - context->ResetRenderTarget(); - context->SetRenderTarget(tile->View()); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, tile8->View()); - context->SetState(_psTileMaxV); - context->DrawFullscreenTriangle(); - RenderTargetPool::Release(tile8); - - // Pass 6 - NeighborMax filter - rtDesc.Width = motionVectorsWidth / tileSize; - rtDesc.Height = motionVectorsHeight / tileSize; - auto neighborMax = RenderTargetPool::Get(rtDesc); - context->ResetRenderTarget(); - context->SetRenderTarget(neighborMax->View()); - context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); - context->BindSR(0, tile->View()); - context->SetState(_psNeighborMax); - context->DrawFullscreenTriangle(); - RenderTargetPool::Release(tile); - - // Pass 7 - Reconstruction pass - context->ResetRenderTarget(); - context->SetRenderTarget(*output); - context->SetViewportAndScissors((float)screenWidth, (float)screenHeight); - context->BindSR(0, input->View()); - context->BindSR(1, vBuffer->View()); - context->BindSR(2, neighborMax->View()); - context->SetState(_psReconstruction); - context->DrawFullscreenTriangle(); - - // Cleanup - context->ResetSR(); - context->ResetRenderTarget(); - RenderTargetPool::Release(vBuffer); - RenderTargetPool::Release(neighborMax); - Swap(output, input); + // .. } diff --git a/Source/Engine/Renderer/MotionBlurPass.h b/Source/Engine/Renderer/MotionBlurPass.h index e4447e5a8..d27003f13 100644 --- a/Source/Engine/Renderer/MotionBlurPass.h +++ b/Source/Engine/Renderer/MotionBlurPass.h @@ -10,43 +10,11 @@ class MotionBlurPass : public RendererPass { private: - PACK_STRUCT(struct Data { - GBufferData GBuffer; - Matrix CurrentVP; - Matrix PreviousVP; - Vector4 TemporalAAJitter; - Vector2 TileMaxOffs; - float VelocityScale; - int32 TileMaxLoop; - float MaxBlurRadius; - float RcpMaxBlurRadius; - Vector2 TexelSize1; - Vector2 TexelSize2; - Vector2 TexelSize4; - Vector2 TexelSizeV; - Vector2 TexelSizeNM; - float LoopCount; - float Dummy0; - Vector2 MotionVectorsTexelSize; - float DebugBlend; - float DebugAmplitude; - int32 DebugColumnCount; - int32 DebugRowCount; - }); PixelFormat _motionVectorsFormat; PixelFormat _velocityFormat; AssetReference _shader; - GPUPipelineState* _psCameraMotionVectors; - GPUPipelineState* _psMotionVectorsDebug; - GPUPipelineState* _psMotionVectorsDebugArrow; - GPUPipelineState* _psVelocitySetup; - GPUPipelineState* _psTileMax1; - GPUPipelineState* _psTileMax2; - GPUPipelineState* _psTileMax4; - GPUPipelineState* _psTileMaxV; - GPUPipelineState* _psNeighborMax; - GPUPipelineState* _psReconstruction; + GPUPipelineState* _psCameraMotionVectors = nullptr; public: @@ -84,15 +52,6 @@ private: void OnShaderReloading(Asset* obj) { _psCameraMotionVectors->ReleaseGPU(); - _psMotionVectorsDebug->ReleaseGPU(); - _psMotionVectorsDebugArrow->ReleaseGPU(); - _psVelocitySetup->ReleaseGPU(); - _psTileMax1->ReleaseGPU(); - _psTileMax2->ReleaseGPU(); - _psTileMax4->ReleaseGPU(); - _psTileMaxV->ReleaseGPU(); - _psNeighborMax->ReleaseGPU(); - _psReconstruction->ReleaseGPU(); invalidateResources(); } #endif diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index b46d624d5..c19be8dc3 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -306,6 +306,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext) #endif renderContext.List->Settings.AntiAliasing.Mode = aaMode; + // Prepare renderContext.View.Prepare(renderContext); renderContext.Buffers->Prepare(); @@ -484,7 +485,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext) context->ResetRenderTarget(); context->SetRenderTarget(task->GetOutputView()); context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight()); - MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View()); + context->Clear(frameBuffer->View(), Color::Black); + //MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View()); return; } diff --git a/Source/Shaders/MotionBlur.shader b/Source/Shaders/MotionBlur.shader index e4199d4a3..53054c799 100644 --- a/Source/Shaders/MotionBlur.shader +++ b/Source/Shaders/MotionBlur.shader @@ -14,27 +14,6 @@ float4x4 CurrentVP; float4x4 PreviousVP; float4 TemporalAAJitter; -// Motion Blur -float2 TileMaxOffs; -float VelocityScale; -int TileMaxLoop; -float MaxBlurRadius; -float RcpMaxBlurRadius; -float2 TexelSize1; -float2 TexelSize2; -float2 TexelSize4; -float2 TexelSizeV; -float2 TexelSizeNM; -float LoopCount; -float Dummy0; -float2 MotionVectorsTexelSize; - -// Motion Vectors Debug Parameters -float DebugBlend; -float DebugAmplitude; -int DebugColumnCount; -int DebugRowCount; - META_CB_END DECLARE_GBUFFERDATA_ACCESS(GBuffer) @@ -43,106 +22,6 @@ Texture2D Input0 : register(t0); Texture2D Input1 : register(t1); Texture2D Input2 : register(t2); -// Calculates the color for the a motion vector debugging -float4 VectorToColor(float2 motionVector) -{ - float phi = atan2(motionVector.x, motionVector.y); - float hue = (phi / PI + 1) * 0.5; - - float r = abs(hue * 6 - 3) - 1; - float g = 2 - abs(hue * 6 - 2); - float b = 2 - abs(hue * 6 - 4); - float a = length(motionVector); - - return saturate(float4(r, g, b, a)); -} - -// Pixel shader for motion vectors debug view -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_MotionVectorsDebug(Quad_VS2PS input) : SV_Target -{ - float4 color = SAMPLE_RT(Input0, input.TexCoord); - float2 motionVector = SAMPLE_RT(Input1, input.TexCoord).rg * (DebugAmplitude * 5.0f); - float4 motionColor = VectorToColor(motionVector); - - float colorRation = saturate(2 - DebugBlend * 2); - float motionColorRatio = saturate(DebugBlend * 2); - color.rgb = lerp(color.rgb * colorRation, motionColor.rgb, motionColor.a * motionColorRatio); - - return color; -} - -// Motion vector arrow data from VS to PS -struct ArrowVaryings -{ - float4 Position : SV_POSITION; - float2 ScreenUV : TEXCOORD; - float4 Color : COLOR; -}; - -META_VS(true, FEATURE_LEVEL_ES2) -ArrowVaryings VS_DebugArrow(uint VertexId : SV_VertexID) -{ - // Screen aspect ratio - float aspect = GBuffer.ScreenSize.x * GBuffer.ScreenSize.w; - float aspectInv = GBuffer.ScreenSize.y * GBuffer.ScreenSize.z; - - // Vertex IDs - uint arrowId = VertexId / 6; - uint pointId = VertexId - arrowId * 6; - - // Column and row number of the arrow - uint row = arrowId / DebugColumnCount; - uint col = arrowId - row * DebugColumnCount; - - // Get the motion vector - float2 uv = float2((col + 0.5) / DebugColumnCount, (row + 0.5) / DebugRowCount); - float2 motionVector = SAMPLE_RT(Input1, uv).rg * DebugAmplitude; - - // Arrow color - float4 color = VectorToColor(motionVector); - - // Arrow transformation - float isEnd = pointId > 0; - float2 direction = normalize(motionVector * float2(aspect, 1)); - float2x2 rotation = float2x2(direction.y, direction.x, -direction.x, direction.y); - float offsetStart = pointId == 3 ? -1 : (pointId == 5 ? 1 : 0); - offsetStart *= isEnd * 0.3f * saturate(length(motionVector) * DebugRowCount); - float2 offset = float2(offsetStart, -abs(offsetStart)); - offset = mul(rotation, offset) * float2(aspectInv, 1); - - // Vertex position in the clip space - float2 pos = motionVector * isEnd + offset * 2 / DebugRowCount + uv * 2.0f - 1.0f; - - // Convert to the screen coordinates - float2 posSS = (pos + 1) * 0.5f * GBuffer.ScreenSize.xy; - posSS = round(posSS); - - // Bring back to the clip space - pos = (posSS + 0.5f) * GBuffer.ScreenSize.zw * 2.0f - 1.0f; - pos.y *= -1; - - // Color tweaks - color.rgb = lerp(color.rgb, 1, 0.5f); - color.a = DebugBlend; - - // Output - ArrowVaryings output; - output.Position = float4(pos, 0, 1); - output.ScreenUV = posSS; - output.Color = color; - return output; -} - -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_DebugArrow(ArrowVaryings input) : SV_Target -{ - // Pseudo anti-aliasing - float aa = length(frac(input.ScreenUV) - 0.5f) / 0.707f; - aa *= (aa * (aa * 0.305306011f + 0.682171111f) + 0.012522878f); - return float4(input.Color.rgb, input.Color.a * aa); -} - // Pixel shader for camera motion vectors META_PS(true, FEATURE_LEVEL_ES2) float4 PS_CameraMotionVectors(Quad_VS2PS input) : SV_Target @@ -169,224 +48,3 @@ float4 PS_CameraMotionVectors(Quad_VS2PS input) : SV_Target return float4(vPosCur - vPosPrev, 0, 1); } - -// Pixel Shader for velocity texture setup -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_VelocitySetup(Quad_VS2PS input) : SV_Target -{ - // Sample the motion vector - float2 v = SAMPLE_RT(Input0, input.TexCoord).rg; - - // Apply the exposure time and convert to the pixel space - v *= (VelocityScale * 0.5f) * GBuffer.ScreenSize.xy; - - // Clamp the vector with the maximum blur radius - v /= max(1.0f, length(v) * RcpMaxBlurRadius); - - // Sample the depth of the pixel - float depth = SAMPLE_RT(Input1, input.TexCoord).r; - GBufferData gBufferData = GetGBufferData(); - depth = LinearizeZ(gBufferData, depth); - - // Pack into 10/10/10/2 format - return float4((v * RcpMaxBlurRadius + 1.0f) * 0.5f, depth, 0.0f); -} - -float2 MaxV(float2 v1, float2 v2) -{ - return dot(v1, v1) < dot(v2, v2) ? v2 : v1; -} - -// Pixel Shader for TileMax filter (2 pixel width with normalization) -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_TileMax1(Quad_VS2PS input) : SV_Target -{ - float4 d = TexelSize1.xyxy * float4(-0.5, -0.5, 0.5, 0.5); - - float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg; - float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg; - float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg; - float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg; - - v1 = (v1 * 2.0f - 1.0f) * MaxBlurRadius; - v2 = (v2 * 2.0f - 1.0f) * MaxBlurRadius; - v3 = (v3 * 2.0f - 1.0f) * MaxBlurRadius; - v4 = (v4 * 2.0f - 1.0f) * MaxBlurRadius; - - return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f); -} - -// Pixel Shader for TileMax filter (2 pixel width) -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_TileMax2(Quad_VS2PS input) : SV_Target -{ - float4 d = TexelSize2.xyxy * float4(-0.5f, -0.5f, 0.5f, 0.5f); - - float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg; - float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg; - float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg; - float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg; - - return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f); -} - -// Pixel Shader for TileMax filter (2 pixel width) -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_TileMax4(Quad_VS2PS input) : SV_Target -{ - float4 d = TexelSize4.xyxy * float4(-0.5f, -0.5f, 0.5f, 0.5f); - - float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg; - float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg; - float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg; - float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg; - - return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f); -} - -// Pixel Shader for TileMax filter (variable width) -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_TileMaxV(Quad_VS2PS input) : SV_Target -{ - float2 uv0 = input.TexCoord + TexelSizeV.xy * TileMaxOffs.xy; - - float2 du = float2(TexelSizeV.x, 0.0); - float2 dv = float2(0.0, TexelSizeV.y); - - float2 vo = 0.0; - - LOOP - for (int x = 0; x < TileMaxLoop; x++) - { - LOOP - for (int y = 0; y < TileMaxLoop; y++) - { - float2 uv = uv0 + du * x + dv * y; - vo = MaxV(vo, SAMPLE_RT(Input0, uv).rg); - } - } - - return float4(vo, 0.0, 0.0); -} - -// Pixel Shader for NeighborMax filter -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_NeighborMax(Quad_VS2PS input) : SV_Target -{ - // Center weight tweak - const float cw = 1.01; - - float4 d = TexelSizeNM.xyxy * float4(1.0, 1.0, -1.0, 0.0); - - float2 v1 = SAMPLE_RT(Input0, input.TexCoord - d.xy).rg; - float2 v2 = SAMPLE_RT(Input0, input.TexCoord - d.wy).rg; - float2 v3 = SAMPLE_RT(Input0, input.TexCoord - d.zy).rg; - - float2 v4 = SAMPLE_RT(Input0, input.TexCoord - d.xw).rg; - float2 v5 = SAMPLE_RT(Input0, input.TexCoord).rg * cw; - float2 v6 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg; - - float2 v7 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg; - float2 v8 = SAMPLE_RT(Input0, input.TexCoord + d.wy).rg; - float2 v9 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg; - - float2 va = MaxV(v1, MaxV(v2, v3)); - float2 vb = MaxV(v4, MaxV(v5, v6)); - float2 vc = MaxV(v7, MaxV(v8, v9)); - - return float4(MaxV(va, MaxV(vb, vc)) * (1.0f / cw), 0.0f, 0.0f); -} - -// Interleaved gradient function from Jimenez 2014 -// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare -float GradientNoise(float2 uv) -{ - uv = floor(uv * GBuffer.ScreenSize.xy); - float f = dot(float2(0.06711056f, 0.00583715f), uv); - return frac(52.9829189f * frac(f)); -} - -// Returns true or false with a given interval -bool Interval(float phase, float interval) -{ - return frac(phase / interval) > 0.499; -} - -// Jitter function for tile lookup -float2 JitterTile(float2 uv) -{ - float rx, ry; - sincos(GradientNoise(uv + float2(2.0f, 0.0f)) * (2.0f * PI), ry, rx); - return float2(rx, ry) * TexelSizeNM.xy * 0.25f; -} - -// Velocity sampling function -float3 SampleVelocity(float2 uv) -{ - float3 v = SAMPLE_RT(Input1, uv).xyz; - return float3((v.xy * 2.0f - 1.0f) * MaxBlurRadius, v.z); -} - -// Pixel Shader for reconstruction filter (applies the motion blur to the frame) -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_Reconstruction(Quad_VS2PS input) : SV_Target -{ - // Sample at the current location - const float4 color = SAMPLE_RT(Input0, input.TexCoord); - const float3 velocity = SampleVelocity(input.TexCoord); - const float velocityLen = max(length(velocity.xy), 0.5); - const float depthInv = 1.0 / velocity.z; - - const float2 velocityMax = SAMPLE_RT(Input2, input.TexCoord + JitterTile(input.TexCoord)).xy; - const float velocityMaxLength = length(velocityMax); - if (velocityMaxLength < 2.0f) - return color; - const float2 velocityWeighted = (velocityLen * 2.0f > velocityMaxLength) ? velocity.xy * (velocityMaxLength / velocityLen) : velocityMax; - - // Calculate the amount of samples - const float sc = floor(min(LoopCount, velocityMaxLength * 0.5f)); - - // Accumlation loop - float backgroudVelocity = max(velocityLen, 1.0f); - const float dt = 1.0f / sc; - const float offsetNoise = (GradientNoise(input.TexCoord) - 0.5f) * dt; - float t = 1.0f - dt * 0.5f; - float count = 0.0f; - float4 sum = 0.0f; - LOOP - while (t > dt * 0.25) - { - // Sampling direction (switched per every two samples) - const float2 sampleVelocity = Interval(count, 4.0) ? velocityWeighted : velocityMax; - - // Sample position (inverted per every sample) - const float samplePosition = (Interval(count, 2.0) ? -t : t) + offsetNoise; - - // Calculate UVs for the sample position - const float2 sampleUV = input.TexCoord + sampleVelocity * samplePosition * GBuffer.ScreenSize.zw; - - // Sample color and velocity with depth - const float3 c = SAMPLE_RT(Input0, sampleUV).rgb; - const float3 velocityDepth = SampleVelocity(sampleUV); - - // Length of the velocity vector - const float foreground = saturate((velocity.z - velocityDepth.z) * 20.0f * depthInv); - const float sampleVelocityLength = lerp(backgroudVelocity, length(velocityDepth.xy), foreground); - - // Apply color accumulation - float weight = saturate(sampleVelocityLength - (velocityMaxLength * abs(samplePosition))) / sampleVelocityLength * (1.2f - t); - sum += float4(c, 1.0) * weight; - - // Calculate the background velocity - backgroudVelocity = max(backgroudVelocity, sampleVelocityLength); - - // Move to the next sample - t = Interval(count, 2.0f) ? t - dt : t; - count += 1.0f; - } - - // Add the center sample - sum += float4(color.rgb, 1.0f) * (1.2f / (backgroudVelocity * sc * 2.0f)); - - return float4(sum.rgb / sum.a, color.a); -} diff --git a/Source/Shaders/TAA.shader b/Source/Shaders/TAA.shader index 436c68186..0949e110d 100644 --- a/Source/Shaders/TAA.shader +++ b/Source/Shaders/TAA.shader @@ -1,151 +1,10 @@ // Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. #include "./Flax/Common.hlsl" -#include "./Flax/GammaCorrectionCommon.hlsl" - -#define USE_TONEMAP 0 - -META_CB_BEGIN(0, Data) -float4 ScreenSize;// x-width, y-height, z-1/width, w-1/height -float4 TaaJitterStrength; // x, y, x/width, y/height -float4 FinalBlendParameters; // x: static, y: dynamic, z: motion amplification, w; sharpness -META_CB_END - -Texture2D Input : register(t0); -Texture2D InputHistory : register(t1); -Texture2D MotionVectors : register(t2); -Texture2D Depth : register(t3); - -float3 Fetch(Texture2D tex, float2 coords) -{ - return tex.SampleLevel(SamplerLinearClamp, coords, 0).rgb; -} - -float3 Map(float3 x) -{ -#if USE_TONEMAP - return FastTonemap(x); -#else - return x; -#endif -} - -float3 Unmap(float3 x) -{ -#if USE_TONEMAP - return FastTonemapInvert(x); -#else - return x; -#endif -} - -float3 ClipToAABB(float3 color, float3 minimum, float3 maximum) -{ - // Note: only clips towards aabb center (but fast!) - float3 center = 0.5 * (maximum + minimum); - float3 extents = 0.5 * (maximum - minimum); - - // This is actually `distance`, however the keyword is reserved - float3 offset = color - center; - - float3 ts = abs(extents / max(offset, 0.0001)); - float t = saturate(min(min(ts.x, ts.y), ts.z)); - return center + offset * t; -} - -float2 GetClosestFragment(float2 uv) -{ - const float2 k = ScreenSize.zw; - - const float4 neighborhood = float4( - SAMPLE_RT(Depth, uv - k).r, - SAMPLE_RT(Depth, uv + float2(k.x, -k.y)).r, - SAMPLE_RT(Depth, uv + float2(-k.x, k.y)).r, - SAMPLE_RT(Depth, uv + k).r - ); - -#if defined(REVERSED_Z) - #define COMPARE_DEPTH(a, b) step(b, a) -#else - #define COMPARE_DEPTH(a, b) step(a, b) -#endif - - float3 result = float3(0.0, 0.0, SAMPLE_RT(Depth, uv).r); - result = lerp(result, float3(-1.0, -1.0, neighborhood.x), COMPARE_DEPTH(neighborhood.x, result.z)); - result = lerp(result, float3( 1.0, -1.0, neighborhood.y), COMPARE_DEPTH(neighborhood.y, result.z)); - result = lerp(result, float3(-1.0, 1.0, neighborhood.z), COMPARE_DEPTH(neighborhood.z, result.z)); - result = lerp(result, float3( 1.0, 1.0, neighborhood.w), COMPARE_DEPTH(neighborhood.w, result.z)); - - return (uv + result.xy * k); -} // Pixel Shader for Temporal Anti-Aliasing META_PS(true, FEATURE_LEVEL_ES2) -META_PERMUTATION_1(IS_ORTHO=0) -META_PERMUTATION_1(IS_ORTHO=1) -void PS(Quad_VS2PS input, out float4 output : SV_Target0, out float4 outputHistory : SV_Target1) +float4 PS(Quad_VS2PS input) : SV_Target0 { - float2 jitter = TaaJitterStrength.zw; - float2 texcoord = input.TexCoord; - const float2 k = ScreenSize.zw; - -#if IS_ORTHO - float2 closest = texcoord; -#else - float2 closest = GetClosestFragment(texcoord); -#endif - - // Sample velocity - float2 velocity = MotionVectors.SampleLevel(SamplerLinearClamp, closest, 0).xy; - - // Sample color and surround - float2 uv = texcoord - jitter; - float3 color = Fetch(Input, uv); - float3 topLeft = Fetch(Input, uv - k); - float3 bottomRight = Fetch(Input, uv + k); - float3 topRight = Fetch(Input, uv + float2(k.x, -k.y)); - float3 bottomLeft = Fetch(Input, uv + float2(-k.x, k.y)); - - float3 corners = 4.0 * (topLeft + bottomRight) - 2.0 * color; - - // Sharpen output - float sharpness = FinalBlendParameters.w; - float3 blur = (topLeft + topRight + bottomLeft + bottomRight) * 0.25; - color += (color - blur) * sharpness; - color = clamp(color, 0.0, HDR_CLAMP_MAX); - - // Tonemap color - float3 average = Map((corners + color) / 7.0); - topLeft = Map(topLeft); - bottomRight = Map(bottomRight); - color = Map(color); - - // Sample history - float3 history = Fetch(InputHistory, texcoord - velocity); - history = Map(history); - - float colorLuma = Luminance(color); - float averageLuma = Luminance(average); - float velocityLength = length(velocity); - float nudge = lerp(4.0, 0.25, velocityLength * 100.0) * abs(averageLuma - colorLuma); - - float3 minimum = min(bottomRight, topLeft) - nudge; - float3 maximum = max(topLeft, bottomRight) + nudge; - - // Clip history sample - history = ClipToAABB(history, minimum, maximum); - - // Blend color with history - //float historyLuma = Luminance(history); - //float weight = 1.0f - saturate(abs(colorLuma - historyLuma) / max(max(colorLuma, historyLuma), 0.2)); - float weight = saturate(velocityLength * FinalBlendParameters.z); - float feedback = lerp(FinalBlendParameters.x, FinalBlendParameters.y, weight * weight); - //feedback = lerp(feedback, 0.02, velocityWeight); - color = Unmap(lerp(color, history, feedback)); - color = clamp(color, 0.0, HDR_CLAMP_MAX); - - output = float4(color, 1); - outputHistory = output; - - //output = float4(1, 0, 0, 1) * feedback; + return float4(0, 0, 0, 0); } From 21cbfec53356468a6031f49bc3bd44d7a46a7281 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Tue, 22 Dec 2020 18:33:06 +0100 Subject: [PATCH 06/11] Fix speed change scrolling being wonky --- Source/Editor/Viewport/EditorViewport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index 42385fd5e..0230ee686 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -968,7 +968,7 @@ namespace FlaxEditor.Viewport _wheelMovementChangeDeltaSum -= step; MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Min(camValueIndex + 1, EditorViewportCameraSpeedValues.Length - 1)]; } - else if (_wheelMovementChangeDeltaSum <= step) + else if (_wheelMovementChangeDeltaSum <= -step) { _wheelMovementChangeDeltaSum += step; MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Max(camValueIndex - 1, 0)]; From a388df2f7454237aa6075c6e3ec52ab0febefe01 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Tue, 22 Dec 2020 22:46:52 +0100 Subject: [PATCH 07/11] Better handle double file extensions on rename Fix #37 --- Source/Editor/Windows/ContentWindow.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index acea1e665..655ac653f 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -296,9 +296,14 @@ namespace FlaxEditor.Windows return; } + // Renaming a file to an extension it already has + if (!item.IsFolder && StringUtils.NormalizeExtension(Path.GetExtension(newShortName)) == StringUtils.NormalizeExtension(Path.GetExtension(item.Path))) + { + newShortName = StringUtils.GetPathWithoutExtension(newShortName); + } + // Check if name is valid - string hint; - if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out hint)) + if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out string hint)) { // Invalid name MessageBox.Show("Given asset name is invalid. " + hint, @@ -317,8 +322,8 @@ namespace FlaxEditor.Windows } // Cache data - var extension = Path.GetExtension(item.Path); - var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, Path.ChangeExtension(newShortName, extension)); + string extension = Path.GetExtension(item.Path); + var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension); // Check if was renaming mock element // Note: we create `_newElement` and then rename it to create new asset From 94822b57d94a89ed7ac4bf35817dc8c93d7dab09 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 23:14:36 +0100 Subject: [PATCH 08/11] Remove dummy logs --- Development/Scripts/Windows/CallBuildTool.bat | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Development/Scripts/Windows/CallBuildTool.bat b/Development/Scripts/Windows/CallBuildTool.bat index 021eeeed2..4d9124776 100644 --- a/Development/Scripts/Windows/CallBuildTool.bat +++ b/Development/Scripts/Windows/CallBuildTool.bat @@ -34,24 +34,16 @@ if errorlevel 1 goto Error_FlaxBuildFailed exit /B 0 :Error_InvalidLocation -echo. echo CallBuildTool ERROR: The script is in invalid directory. -echo. goto Exit :Error_NoVisualStudioEnvironment -echo. echo CallBuildTool ERROR: Missing Visual Studio 2015 or newer. -echo. goto Exit :Error_CompilationFailed -echo. echo CallBuildTool ERROR: Failed to compile Flax.Build project. -echo. goto Exit :Error_FlaxBuildFailed -echo. echo CallBuildTool ERROR: Flax.Build tool failed. -echo. goto Exit :Exit exit /B 1 From 38cd840a66e1ec9b5fc310b54fff327a9217974d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 23:18:23 +0100 Subject: [PATCH 09/11] Tweak readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 06b3fe1f1..1ad9f7ce4 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,6 @@ This repository contains full source code of the Flax (excluding NDA-protected p * [Forum](https://forum.flaxengine.com) * [Roadmap](https://trello.com/b/NQjLXRCP/flax-roadmap) -# Flax plugin for Visual Studio - -Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS). - # Screenshots ![rendering](Development/Images/flax-pic-1.jpg "Rendering") @@ -53,6 +49,10 @@ Follow the instructions below to compile and run the engine from source. * Open workspace with Visual Code * Build and run +# Flax plugin for Visual Studio + +Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS). + ## Workspace directory - **Binaries/** - executable files From 8198b7329775a01e3d0ed1b3bdd37860a2cb1889 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Dec 2020 23:29:42 +0100 Subject: [PATCH 10/11] Add license files for all third party modules explicitly (even if using predefined license defined in config) --- Source/ThirdParty/LZ4/LICENSE.txt | 33 +++++++++++++++++++ Source/ThirdParty/LZ4/lz4.Build.cs | 1 + Source/ThirdParty/OpenFBX/LICENSE.txt | 21 ++++++++++++ Source/ThirdParty/OpenFBX/OpenFBX.Build.cs | 1 + .../ThirdParty/UniversalAnalytics/LICENSE.txt | 29 ++++++++++++++++ .../UniversalAnalytics.Build.cs | 1 + Source/ThirdParty/fmt/fmt.Build.cs | 1 + .../meshoptimizer/meshoptimizer.Build.cs | 1 + Source/ThirdParty/pugixml/pugixml.Build.cs | 1 + .../ThirdParty/rapidjson/rapidjson.Build.cs | 1 + .../recastnavigation.Build.cs | 1 + Source/ThirdParty/volk/LICENSE.txt | 19 +++++++++++ Source/ThirdParty/volk/volk.Build.cs | 1 + .../Flax.Build/Build/ThirdPartyModule.cs | 6 ++-- 14 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 Source/ThirdParty/LZ4/LICENSE.txt create mode 100644 Source/ThirdParty/OpenFBX/LICENSE.txt create mode 100644 Source/ThirdParty/UniversalAnalytics/LICENSE.txt create mode 100644 Source/ThirdParty/volk/LICENSE.txt diff --git a/Source/ThirdParty/LZ4/LICENSE.txt b/Source/ThirdParty/LZ4/LICENSE.txt new file mode 100644 index 000000000..fafb37e2d --- /dev/null +++ b/Source/ThirdParty/LZ4/LICENSE.txt @@ -0,0 +1,33 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2017, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ \ No newline at end of file diff --git a/Source/ThirdParty/LZ4/lz4.Build.cs b/Source/ThirdParty/LZ4/lz4.Build.cs index 28ef6096d..397da1243 100644 --- a/Source/ThirdParty/LZ4/lz4.Build.cs +++ b/Source/ThirdParty/LZ4/lz4.Build.cs @@ -13,5 +13,6 @@ public class lz4 : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.BSD2Clause; + LicenseFilePath = "LICENSE.txt"; } } diff --git a/Source/ThirdParty/OpenFBX/LICENSE.txt b/Source/ThirdParty/OpenFBX/LICENSE.txt new file mode 100644 index 000000000..45cc0d228 --- /dev/null +++ b/Source/ThirdParty/OpenFBX/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Mikulas Florek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Source/ThirdParty/OpenFBX/OpenFBX.Build.cs b/Source/ThirdParty/OpenFBX/OpenFBX.Build.cs index 63aa380e6..0edd06dd5 100644 --- a/Source/ThirdParty/OpenFBX/OpenFBX.Build.cs +++ b/Source/ThirdParty/OpenFBX/OpenFBX.Build.cs @@ -13,5 +13,6 @@ public class OpenFBX : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.MIT; + LicenseFilePath = "LICENSE.txt"; } } diff --git a/Source/ThirdParty/UniversalAnalytics/LICENSE.txt b/Source/ThirdParty/UniversalAnalytics/LICENSE.txt new file mode 100644 index 000000000..be81fa7d9 --- /dev/null +++ b/Source/ThirdParty/UniversalAnalytics/LICENSE.txt @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2013-2014, Adswerve, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Source/ThirdParty/UniversalAnalytics/UniversalAnalytics.Build.cs b/Source/ThirdParty/UniversalAnalytics/UniversalAnalytics.Build.cs index eebe5ad1f..d1a0ee2bb 100644 --- a/Source/ThirdParty/UniversalAnalytics/UniversalAnalytics.Build.cs +++ b/Source/ThirdParty/UniversalAnalytics/UniversalAnalytics.Build.cs @@ -14,6 +14,7 @@ public class UniversalAnalytics : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.BSD3Clause; + LicenseFilePath = "LICENSE.txt"; } /// diff --git a/Source/ThirdParty/fmt/fmt.Build.cs b/Source/ThirdParty/fmt/fmt.Build.cs index bea9da717..7264db21a 100644 --- a/Source/ThirdParty/fmt/fmt.Build.cs +++ b/Source/ThirdParty/fmt/fmt.Build.cs @@ -15,6 +15,7 @@ public class fmt : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.BSD2Clause; + LicenseFilePath = "cppformat license.txt"; } /// diff --git a/Source/ThirdParty/meshoptimizer/meshoptimizer.Build.cs b/Source/ThirdParty/meshoptimizer/meshoptimizer.Build.cs index b1051d492..c2c4d4488 100644 --- a/Source/ThirdParty/meshoptimizer/meshoptimizer.Build.cs +++ b/Source/ThirdParty/meshoptimizer/meshoptimizer.Build.cs @@ -13,5 +13,6 @@ public class meshoptimizer : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.MIT; + LicenseFilePath = "LICENSE.md"; } } diff --git a/Source/ThirdParty/pugixml/pugixml.Build.cs b/Source/ThirdParty/pugixml/pugixml.Build.cs index 6f5342162..e7efff160 100644 --- a/Source/ThirdParty/pugixml/pugixml.Build.cs +++ b/Source/ThirdParty/pugixml/pugixml.Build.cs @@ -13,5 +13,6 @@ public class pugixml : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.MIT; + LicenseFilePath = "pugixml license.txt"; } } diff --git a/Source/ThirdParty/rapidjson/rapidjson.Build.cs b/Source/ThirdParty/rapidjson/rapidjson.Build.cs index bc24587c8..b2a18b039 100644 --- a/Source/ThirdParty/rapidjson/rapidjson.Build.cs +++ b/Source/ThirdParty/rapidjson/rapidjson.Build.cs @@ -15,6 +15,7 @@ public class rapidjson : HeaderOnlyModule base.Init(); LicenseType = LicenseTypes.MIT; + LicenseFilePath = "RapidJSON license.txt"; } /// diff --git a/Source/ThirdParty/recastnavigation/recastnavigation.Build.cs b/Source/ThirdParty/recastnavigation/recastnavigation.Build.cs index f5420a335..b01dfb3bf 100644 --- a/Source/ThirdParty/recastnavigation/recastnavigation.Build.cs +++ b/Source/ThirdParty/recastnavigation/recastnavigation.Build.cs @@ -13,5 +13,6 @@ public class recastnavigation : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.zLib; + LicenseFilePath = "License.txt"; } } diff --git a/Source/ThirdParty/volk/LICENSE.txt b/Source/ThirdParty/volk/LICENSE.txt new file mode 100644 index 000000000..da3caa7cd --- /dev/null +++ b/Source/ThirdParty/volk/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Arseny Kapoulkine + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Source/ThirdParty/volk/volk.Build.cs b/Source/ThirdParty/volk/volk.Build.cs index 5247e08ec..772ad4894 100644 --- a/Source/ThirdParty/volk/volk.Build.cs +++ b/Source/ThirdParty/volk/volk.Build.cs @@ -14,6 +14,7 @@ public class volk : ThirdPartyModule base.Init(); LicenseType = LicenseTypes.MIT; + LicenseFilePath = "LICENSE.txt"; } /// diff --git a/Source/Tools/Flax.Build/Build/ThirdPartyModule.cs b/Source/Tools/Flax.Build/Build/ThirdPartyModule.cs index a32144ffe..9743d1608 100644 --- a/Source/Tools/Flax.Build/Build/ThirdPartyModule.cs +++ b/Source/Tools/Flax.Build/Build/ThirdPartyModule.cs @@ -199,9 +199,9 @@ namespace Flax.Build // Perform license validation if (LicenseType == LicenseTypes.Invalid) throw new Exception(string.Format("Cannot build module {0}. Third Party modules must have license type specified.", Name)); - if (LicenseType == LicenseTypes.Custom && LicenseFilePath == null) - throw new Exception(string.Format("Cannot build module {0}. Third Party modules with Custom license must have license file specified.", Name)); - if (LicenseFilePath != null && !File.Exists(Path.Combine(FolderPath, LicenseFilePath))) + if (LicenseFilePath == null) + throw new Exception(string.Format("Cannot build module {0}. Third Party modules must have license file specified.", Name)); + if (!File.Exists(Path.Combine(FolderPath, LicenseFilePath))) throw new Exception(string.Format("Cannot build module {0}. Specified license file does not exist.", Name)); } From 2acad9963fb97004448a027f193da966770996ee Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 23 Dec 2020 10:14:51 +0100 Subject: [PATCH 11/11] Fix #41 --- Source/Engine/Utilities/StringUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Utilities/StringUtils.cs b/Source/Engine/Utilities/StringUtils.cs index 6aa2eb986..de011bfe6 100644 --- a/Source/Engine/Utilities/StringUtils.cs +++ b/Source/Engine/Utilities/StringUtils.cs @@ -92,7 +92,7 @@ namespace FlaxEngine /// The normalized extension. public static string NormalizeExtension(string extension) { - if (extension[0] == '.') + if (extension.Length != 0 && extension[0] == '.') extension = extension.Remove(0, 1); return extension.ToLower(); }