diff --git a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax index b07a99dc8..69a6311df 100644 --- a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax +++ b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ceb358badb21ed5be2b5754f3028e40887bee543423ab50c1c6700614113708c -size 16241 +oid sha256:0a24be8b457a31c8c7edcabf21481899c34d20e624adf3ef00a70ef66d67e1c5 +size 18609 diff --git a/Content/Shaders/BakeLightmap.flax b/Content/Shaders/BakeLightmap.flax index 7c38ec6c5..da1d4f0fc 100644 --- a/Content/Shaders/BakeLightmap.flax +++ b/Content/Shaders/BakeLightmap.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ab9a4d7377684f4d51b01c6cdbb44a80249d39ca3ebb0a443fcc0c6beb84ffc -size 15755 +oid sha256:595844ed7279b8c421f62c3f9d243a7c9cbba6e7063ec19c3009c34ea894ab15 +size 15783 diff --git a/Content/Shaders/ColorGrading.flax b/Content/Shaders/ColorGrading.flax index 113e33263..7dd977e12 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:5df0bf3bac162f4999f97080d4f3a573ab2cf2bdbc1afe960a7ee4c5fe94cdfe -size 12373 +oid sha256:b51bdd2a76045479c8bb6209fdf9bd2af5941c5ccc607e86672d268e0d75761c +size 12387 diff --git a/Content/Shaders/DebugDraw.flax b/Content/Shaders/DebugDraw.flax index c3626e1a8..d5b2a7be5 100644 --- a/Content/Shaders/DebugDraw.flax +++ b/Content/Shaders/DebugDraw.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:672cef38b8d17a221c8615aef74967556d21418e14c6bf669f279b79c3cff8dc -size 1948 +oid sha256:7cd49c91260912c5e169c441529d0e798010662b1469c17be18d6c8fd3b39eb6 +size 1959 diff --git a/Content/Shaders/GBuffer.flax b/Content/Shaders/GBuffer.flax index 0d2d9b4a0..4f2309115 100644 --- a/Content/Shaders/GBuffer.flax +++ b/Content/Shaders/GBuffer.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfbd11dc6e19b6fc8837d7f5275524baa333f24184395358b945c9cbf95b2dda -size 3134 +oid sha256:0c4eca231e0b6f782dda324d47b04f13d9409fee9ae7705784ea90e3f2e34ae9 +size 3141 diff --git a/Content/Shaders/GI/GlobalSurfaceAtlas.flax b/Content/Shaders/GI/GlobalSurfaceAtlas.flax index a5b50780a..e9b8056dd 100644 --- a/Content/Shaders/GI/GlobalSurfaceAtlas.flax +++ b/Content/Shaders/GI/GlobalSurfaceAtlas.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5da6c9b625db26134d72eb64524807f6e0ca2d8472f2c0ced1ed689f82834c7 -size 14117 +oid sha256:4b9a391babc1720e8c5bdb2f64d3d4c8acdb94d389819c7c32de6606d048b5cb +size 14141 diff --git a/Content/Shaders/GUI.flax b/Content/Shaders/GUI.flax index dbe2e0c50..04d95f3c5 100644 --- a/Content/Shaders/GUI.flax +++ b/Content/Shaders/GUI.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae42619af35655dbea1f99555060d88686adf0dd31d69e94a8c9a4a6753d7495 -size 4833 +oid sha256:bd48767593f1d5a8b6d3231e80b167e0c895cf42dcd9847bd4ad4d52496c84c1 +size 4861 diff --git a/Content/Shaders/MultiScaler.flax b/Content/Shaders/MultiScaler.flax index 8883ba99a..f975da012 100644 --- a/Content/Shaders/MultiScaler.flax +++ b/Content/Shaders/MultiScaler.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55757ff511c6290062b5f050109e520f7b0db6140605b9c69def1e9c788525f3 -size 6903 +oid sha256:b84982175ad5f606ff3c1fbe91a09e43a734ff2d0f436e31665d4dfb9dc3094b +size 7088 diff --git a/Content/Shaders/Quad.flax b/Content/Shaders/Quad.flax index f73292191..3a3422839 100644 --- a/Content/Shaders/Quad.flax +++ b/Content/Shaders/Quad.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7be75cc2c4dc8b815ca3dca0828b7181d3fb7874cddac97e1ca7a563832b018 -size 4059 +oid sha256:512a5a44a2e04cf0c0029da894cd7d0cf53dc9254da2c5eab4f6b9eff7f60cd8 +size 4087 diff --git a/Content/Shaders/SMAA.flax b/Content/Shaders/SMAA.flax index 506781e15..0ce75b266 100644 --- a/Content/Shaders/SMAA.flax +++ b/Content/Shaders/SMAA.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:013970c677da74c2eb300ee81d6aa6f996dbfaaa74abe13cc76329d77b4dab48 -size 46439 +oid sha256:3128227f815eb1b8c126362c378bdd1089aa75995f7380a38f3dbef6f2acba58 +size 46481 diff --git a/Content/Shaders/SSR.flax b/Content/Shaders/SSR.flax index f286e8f45..eff8fa529 100644 --- a/Content/Shaders/SSR.flax +++ b/Content/Shaders/SSR.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e607712c48bd2484fb5bce5fa3f5aa2a4a05d0c03e0f24483b7eb1463d954263 -size 11592 +oid sha256:95928c48d4140f7c01738b18511a0bf938350d693ccbf8397b999cb1917bb673 +size 11587 diff --git a/Content/Shaders/Shadows.flax b/Content/Shaders/Shadows.flax index d29340328..1ceb5616e 100644 --- a/Content/Shaders/Shadows.flax +++ b/Content/Shaders/Shadows.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b22f97a46708fead33de675a0186d34da6f845ca1ac61bab63c1c8f12dbd44b4 -size 7029 +oid sha256:4bb56c7ebd4ba97efa7dde510a6c5bd5c43370f1e0d3043cddb57e83426aedbe +size 6996 diff --git a/Content/Shaders/VolumetricFog.flax b/Content/Shaders/VolumetricFog.flax index 2a2bc2a17..776d40192 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:a8ed390d9a555003ff888c3fce208c6a3d413aa55f230566eb3f6cfe6d5f90df -size 13195 +oid sha256:ebfe9b3147ca7b6e4711500c3938ea6973b3414d0be9cd900a36fb39f1624585 +size 13185 diff --git a/Flax.flaxproj b/Flax.flaxproj index fadf436c3..b93e14df4 100644 --- a/Flax.flaxproj +++ b/Flax.flaxproj @@ -4,7 +4,7 @@ "Major": 1, "Minor": 13, "Revision": 0, - "Build": 7002 + "Build": 7003 }, "Company": "Flax", "Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.", @@ -13,6 +13,7 @@ "Configuration": { "UseCSharp": true, "UseLargeWorlds": false, + "UseReverseZ": true, "UseDotNet": true, "Windows": { "UseSDL": false, diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp index a85973964..5fd61e39c 100644 --- a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp +++ b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp @@ -50,6 +50,10 @@ #endif #include "FlaxEngine.Gen.h" +#ifndef REVERSE_Z +#define REVERSE_Z 0 +#endif + Dictionary CookAssetsStep::AssetProcessors; void IBuildCache::InvalidateCacheShaders() @@ -233,6 +237,11 @@ void CookAssetsStep::CacheData::Load(CookingData& data) LOG(Info, "{0} option has been modified.", TEXT("ShadersGenerateDebugData")); invalidateShaders = true; } + if (REVERSE_Z != Settings.Global.ShadersReverseZ) + { + LOG(Info, "{0} option has been modified.", TEXT("ShadersReverseZ")); + invalidateShaders = true; + } #if PLATFORM_TOOLS_WINDOWS if (data.Platform == BuildPlatform::Windows32 || data.Platform == BuildPlatform::Windows64) { @@ -1076,6 +1085,7 @@ bool CookAssetsStep::Perform(CookingData& data) { cache.Settings.Global.ShadersNoOptimize = buildSettings->ShadersNoOptimize; cache.Settings.Global.ShadersGenerateDebugData = buildSettings->ShadersGenerateDebugData; + cache.Settings.Global.ShadersReverseZ = REVERSE_Z; cache.Settings.Global.StreamingSettingsAssetId = gameSettings->Streaming; cache.Settings.Global.ShadersVersion = GPU_SHADER_CACHE_VERSION; cache.Settings.Global.MaterialGraphVersion = MATERIAL_GRAPH_VERSION; diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.h b/Source/Editor/Cooker/Steps/CookAssetsStep.h index f896d9803..612b363dd 100644 --- a/Source/Editor/Cooker/Steps/CookAssetsStep.h +++ b/Source/Editor/Cooker/Steps/CookAssetsStep.h @@ -97,6 +97,7 @@ public: { bool ShadersNoOptimize; bool ShadersGenerateDebugData; + bool ShadersReverseZ; Guid StreamingSettingsAssetId; int32 ShadersVersion; int32 MaterialGraphVersion; diff --git a/Source/Editor/Gizmo/SelectionOutline.cs b/Source/Editor/Gizmo/SelectionOutline.cs index 410650e4f..2f351b8d8 100644 --- a/Source/Editor/Gizmo/SelectionOutline.cs +++ b/Source/Editor/Gizmo/SelectionOutline.cs @@ -139,15 +139,11 @@ namespace FlaxEditor.Gizmo DrawSelectionDepth(context, renderContext.Task, customDepth); _actors.Clear(); - var near = renderContext.View.Near; - var far = renderContext.View.Far; - var projection = renderContext.View.Projection; - // Render outline _material.SetParameterValue("OutlineColor0", _color0); _material.SetParameterValue("OutlineColor1", _color1); _material.SetParameterValue("CustomDepth", customDepth); - _material.SetParameterValue("ViewInfo", new Float4(1.0f / projection.M11, 1.0f / projection.M22, far / (far - near), (-far * near) / (far - near) / far)); + _material.SetParameterValue("ViewInfo", renderContext.View.ViewInfo); Renderer.DrawPostFxMaterial(context, ref renderContext, _material, output, input.View()); // Cleanup diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index fa5724780..b8d0d8515 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -1497,9 +1497,14 @@ namespace FlaxEditor.Viewport Matrix.Multiply(ref v, ref p, out var ivp); ivp.Invert(); - // Create near and far points - var nearPoint = new Vector3(mousePosition, _nearPlane); - var farPoint = new Vector3(mousePosition, _farPlane); + // Create near and far points, with device depth of 1 and 0 respectively +#if REVERSE_Z + var nearPoint = new Vector3(mousePosition, 1.0f); + var farPoint = new Vector3(mousePosition, 0.0f); +#else + var nearPoint = new Vector3(mousePosition, 0.0f); + var farPoint = new Vector3(mousePosition, 1.0f); +#endif viewport.Unproject(ref nearPoint, ref ivp, out nearPoint); viewport.Unproject(ref farPoint, ref ivp, out farPoint); diff --git a/Source/Engine/Core/Math/BoundingFrustum.cpp b/Source/Engine/Core/Math/BoundingFrustum.cpp index e0697ce5e..2eab04a40 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.cpp +++ b/Source/Engine/Core/Math/BoundingFrustum.cpp @@ -59,6 +59,11 @@ void BoundingFrustum::SetMatrix(const Matrix& matrix) _pFar.Normal.Z = matrix.M34 - matrix.M33; _pFar.D = matrix.M44 - matrix.M43; _pFar.Normalize(); + +#if REVERSE_Z + // Swap far and near planes if reverse z + Swap(_pFar, _pNear); +#endif } Plane BoundingFrustum::GetPlane(int32 index) const diff --git a/Source/Engine/Core/Math/BoundingFrustum.cs b/Source/Engine/Core/Math/BoundingFrustum.cs index 4f1e27e1e..0b295c7d5 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.cs +++ b/Source/Engine/Core/Math/BoundingFrustum.cs @@ -243,6 +243,11 @@ namespace FlaxEngine far.Normal.Z = matrix.M34 - matrix.M33; far.D = matrix.M44 - matrix.M43; far.Normalize(); + +#if REVERSE_Z + // Swap far and near planes if reverse z + (near, far) = (far, near); +#endif } private static Vector3 Get3PlanesInterPoint(ref Plane p1, ref Plane p2, ref Plane p3) diff --git a/Source/Engine/Core/Math/Matrix.cpp b/Source/Engine/Core/Math/Matrix.cpp index f8ee50c42..f3e69df49 100644 --- a/Source/Engine/Core/Math/Matrix.cpp +++ b/Source/Engine/Core/Math/Matrix.cpp @@ -522,10 +522,15 @@ void Matrix::OrthoOffCenter(float left, float right, float bottom, float top, fl result = Identity; result.M11 = 2.0f / (right - left); result.M22 = 2.0f / (top - bottom); - result.M33 = zRange; result.M41 = (left + right) / (left - right); result.M42 = (top + bottom) / (bottom - top); +#if REVERSE_Z + result.M33 = -zRange; + result.M43 = zFar * zRange; +#else + result.M33 = zRange; result.M43 = -zNear * zRange; +#endif } void Matrix::PerspectiveFov(float fov, float aspect, float zNear, float zFar, Matrix& result) @@ -541,16 +546,21 @@ void Matrix::PerspectiveFov(float fov, float aspect, float zNear, float zFar, Ma void Matrix::PerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, Matrix& result) { - const float zRange = zFar / (zFar - zNear); + const float zRange = 1.0f / (zFar - zNear); result = Zero; result.M11 = 2.0f * zNear / (right - left); result.M22 = 2.0f * zNear / (top - bottom); result.M31 = (left + right) / (left - right); result.M32 = (top + bottom) / (bottom - top); - result.M33 = zRange; result.M34 = 1.0f; - result.M43 = -zNear * zRange; +#if REVERSE_Z + result.M33 = -zNear * zRange; + result.M43 = zFar * zNear * zRange; +#else + result.M33 = zFar * zRange; + result.M43 = -zFar * zNear * zRange; +#endif } void Matrix::RotationX(float angle, Matrix& result) diff --git a/Source/Engine/Core/Math/Matrix.cs b/Source/Engine/Core/Math/Matrix.cs index 07ab2dea9..cbec2f119 100644 --- a/Source/Engine/Core/Math/Matrix.cs +++ b/Source/Engine/Core/Math/Matrix.cs @@ -2176,10 +2176,15 @@ namespace FlaxEngine result = Identity; result.M11 = 2.0f / (right - left); result.M22 = 2.0f / (top - bottom); - result.M33 = zRange; result.M41 = (left + right) / (left - right); result.M42 = (top + bottom) / (bottom - top); +#if REVERSE_Z + result.M33 = -zRange; + result.M43 = zfar * zRange; +#else + result.M33 = zRange; result.M43 = -znear * zRange; +#endif } /// @@ -2238,14 +2243,19 @@ namespace FlaxEngine public static void PerspectiveFov(float fov, float aspect, float znear, float zfar, out Matrix result) { var yScale = (float)(1.0f / Math.Tan(fov * 0.5f)); - var q = zfar / (zfar - znear); + var zRange = 1.0f / (zfar - znear); result = new Matrix { M11 = yScale / aspect, M22 = yScale, - M33 = q, M34 = 1.0f, - M43 = -q * znear, +#if REVERSE_Z + M33 = -znear * zRange, + M43 = znear * zfar * zRange, +#else + M33 = zfar * zRange, + M43 = -znear * zfar * zRange, +#endif }; } @@ -2275,16 +2285,21 @@ namespace FlaxEngine /// When the method completes, contains the created projection matrix. public static void PerspectiveOffCenter(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) { - float zRange = zfar / (zfar - znear); + float zRange = 1.0f / (zfar - znear); result = new Matrix { M11 = 2.0f * znear / (right - left), M22 = 2.0f * znear / (top - bottom), M31 = (left + right) / (left - right), M32 = (top + bottom) / (bottom - top), - M33 = zRange, M34 = 1.0f, - M43 = -znear * zRange, +#if REVERSE_Z + M33 = -znear * zRange, + M43 = znear * zfar * zRange, +#else + M33 = zfar * zRange, + M43 = -znear * zfar * zRange, +#endif }; } diff --git a/Source/Engine/Core/Math/Viewport.cs b/Source/Engine/Core/Math/Viewport.cs index f2be10457..b4ff20dd9 100644 --- a/Source/Engine/Core/Math/Viewport.cs +++ b/Source/Engine/Core/Math/Viewport.cs @@ -296,15 +296,13 @@ namespace FlaxEngine /// /// Converts a screen space point into a corresponding point in world space. /// - /// The vector to project. + /// The vector to project, screen uv and device depth. /// The projection matrix. /// The view matrix. - /// The world matrix. /// The unprojected Vector. - public Vector3 Unproject(Vector3 source, Matrix projection, Matrix view, Matrix world) + public Vector3 Unproject(Vector3 source, Matrix projection, Matrix view) { - Matrix.Multiply(ref world, ref view, out Matrix matrix); - Matrix.Multiply(ref matrix, ref projection, out matrix); + Matrix.Multiply(ref view, ref projection, out Matrix matrix); Matrix.Invert(ref matrix, out matrix); Unproject(ref source, ref matrix, out Vector3 vector); @@ -314,8 +312,8 @@ namespace FlaxEngine /// /// Converts a screen space point into a corresponding point in world space. /// - /// The vector to project. - /// An inverted combined WorldViewProjection matrix. + /// The vector to project, screen uv and device depth. + /// An inverted combined ViewProjection matrix. /// The unprojected vector. public void Unproject(ref Vector3 source, ref Matrix matrix, out Vector3 vector) { diff --git a/Source/Engine/Graphics/Enums.h b/Source/Engine/Graphics/Enums.h index 0e174c67e..9d38589a2 100644 --- a/Source/Engine/Graphics/Enums.h +++ b/Source/Engine/Graphics/Enums.h @@ -629,6 +629,17 @@ public: uint32 GetHash(const BlendingMode& key); +// Temp defines to put them into ComparisonFunc enum conditionally +#if REVERSE_Z +#define REVERSE_Z_COMP_DEFAULT 5 +#define REVERSE_Z_COMP_DEFAULT_INV 2 +#define REVERSE_Z_COMP_DEFAULT_EQ 7 +#else +#define REVERSE_Z_COMP_DEFAULT 2 +#define REVERSE_Z_COMP_DEFAULT_INV 5 +#define REVERSE_Z_COMP_DEFAULT_EQ 4 +#endif + /// /// Comparison function modes /// @@ -651,9 +662,21 @@ API_ENUM() enum class ComparisonFunc : byte // Always pass the comparison. Always = 8, - API_ENUM(Attributes="HideInEditor") MAX + API_ENUM(Attributes="HideInEditor") MAX, + + // Default comparision when rendering scene objects (Less or Greater). + API_ENUM(Attributes="HideInEditor") Default = REVERSE_Z_COMP_DEFAULT, + // Default comparision when rendering scene objects inverted (Greater or Less). + API_ENUM(Attributes="HideInEditor") DefaultInv = REVERSE_Z_COMP_DEFAULT_INV, + // Default comparision when rendering scene objects with equal (LessEqual or GreaterEqual). + API_ENUM(Attributes="HideInEditor") DefaultEqual = REVERSE_Z_COMP_DEFAULT_EQ, }; +// Remove temp defines to plug conditional value into the enum +#undef REVERSE_Z_COMP_DEFAULT +#undef REVERSE_Z_COMP_DEFAULT_INV +#undef REVERSE_Z_COMP_DEFAULT_EQ + /// /// Rendering quality levels. /// diff --git a/Source/Engine/Graphics/GPUContext.h b/Source/Engine/Graphics/GPUContext.h index 3a103d3da..f479ef82b 100644 --- a/Source/Engine/Graphics/GPUContext.h +++ b/Source/Engine/Graphics/GPUContext.h @@ -14,6 +14,16 @@ #undef MemoryBarrier #endif +#if REVERSE_Z +#define GPU_DEPTH_RANGE_MIN 1.0f +#define GPU_DEPTH_RANGE_MAX 0.0f +#define GPU_DEPTH_RANGE_BOUNDS(min, max) max, min +#else +#define GPU_DEPTH_RANGE_MIN 0.0f +#define GPU_DEPTH_RANGE_MAX 1.0f +#define GPU_DEPTH_RANGE_BOUNDS(min, max) min, max +#endif + class GPUConstantBuffer; class GPUShaderProgramCS; class GPUBuffer; @@ -208,7 +218,7 @@ public: /// The depth buffer to clear. /// The clear depth value. /// The clear stencil value. - API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = 1.0f, uint8 stencilValue = 0) = 0; + API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = GPU_DEPTH_RANGE_MAX, uint8 stencilValue = 0) = 0; /// /// Clears an unordered access buffer with a float value. @@ -628,9 +638,10 @@ public: /// /// Sets the minimum and maximum depth values for depth bounds test. /// + /// Both values must be between 0.0 and 1.0, MinDepth must be less than or equal to MaxDepth. /// The minimum value for depth bound test. /// The maximum value for depth bound test. - API_FUNCTION() virtual void SetDepthBounds(float minDepth, float maxDepth) = 0; + API_FUNCTION() virtual void SetDepthBounds(float minDepth = 0.0f, float maxDepth = 1.0f) = 0; public: /// diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index c96dcc0a3..1f46c7150 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -160,7 +160,7 @@ GPUPipelineState::Description GPUPipelineState::Description::Default = true, // DepthWriteEnable true, // DepthClipEnable false, // DepthBoundsEnable - ComparisonFunc::Less, // DepthFunc + ComparisonFunc::Default, // DepthFunc false, // StencilEnable 0xff, // StencilReadMask 0xff, // StencilWriteMask @@ -185,7 +185,7 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultNoDepth = false, // DepthWriteEnable false, // DepthClipEnable false, // DepthBoundsEnable - ComparisonFunc::Less, // DepthFunc + ComparisonFunc::Default, // DepthFunc false, // StencilEnable 0xff, // StencilReadMask 0xff, // StencilWriteMask @@ -210,7 +210,7 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultFullscreenTr false, // DepthWriteEnable false, // DepthClipEnable false, // DepthBoundsEnable - ComparisonFunc::Less, // DepthFunc + ComparisonFunc::Default, // DepthFunc false, // StencilEnable 0xff, // StencilReadMask 0xff, // StencilWriteMask diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index ea052aa84..a409c4a89 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -182,7 +182,7 @@ bool DeferredMaterialShader::Load() // Motion Vectors pass psDesc.DepthWriteEnable = false; psDesc.DepthEnable = true; - psDesc.DepthFunc = ComparisonFunc::LessEqual; + psDesc.DepthFunc = ComparisonFunc::DefaultEqual; psDesc.VS = _shader->GetVS("VS"); psDesc.PS = _shader->GetPS("PS_MotionVectors"); _cache.MotionVectors.Init(psDesc); @@ -200,7 +200,7 @@ bool DeferredMaterialShader::Load() psDesc.DepthClipEnable = false; psDesc.DepthWriteEnable = true; psDesc.DepthEnable = true; - psDesc.DepthFunc = ComparisonFunc::Less; + psDesc.DepthFunc = ComparisonFunc::Default; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.HS = nullptr; psDesc.DS = nullptr; diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp index 6260163f4..de19f51f0 100644 --- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp @@ -178,7 +178,11 @@ bool DeformableMaterialShader::Load() psDesc.DepthClipEnable = false; psDesc.DepthWriteEnable = true; psDesc.DepthEnable = true; +#if REVERSE_Z + psDesc.DepthFunc = ComparisonFunc::Greater; +#else psDesc.DepthFunc = ComparisonFunc::Less; +#endif psDesc.HS = nullptr; psDesc.DS = nullptr; _cache.Depth.Init(psDesc); diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index f5897fc46..f22b7d065 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -185,7 +185,7 @@ bool ForwardMaterialShader::Load() psDesc.DepthClipEnable = false; psDesc.DepthWriteEnable = true; psDesc.DepthEnable = true; - psDesc.DepthFunc = ComparisonFunc::Less; + psDesc.DepthFunc = ComparisonFunc::Default; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.HS = nullptr; psDesc.DS = nullptr; diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp index bb0796234..b9a1189d9 100644 --- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp @@ -189,7 +189,7 @@ bool TerrainMaterialShader::Load() psDesc.DepthClipEnable = false; psDesc.DepthWriteEnable = true; psDesc.DepthEnable = true; - psDesc.DepthFunc = ComparisonFunc::Less; + psDesc.DepthFunc = ComparisonFunc::Default; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.HS = nullptr; psDesc.DS = nullptr; diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index 5a7ca9079..e1d94b1a9 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -684,6 +684,20 @@ float RenderTools::TemporalHalton(int32 index, int32 base) Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoint, const Float3& farPoint) { +#if REVERSE_Z + Float3 viewNearPoint = Float3::Transform(nearPoint, view.View); + Float3 viewFarPoint = Float3::Transform(farPoint, view.View); + + viewNearPoint.Z = Math::Max(viewNearPoint.Z, view.Near); + viewFarPoint.Z = Math::Min(viewFarPoint.Z, view.Far); + + Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewNearPoint.Z, 1)); + Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewFarPoint.Z, 1)); + clipNearPoint /= clipNearPoint.W; + clipFarPoint /= clipFarPoint.W; + + return Float2(clipNearPoint.Z, clipFarPoint.Z); +#else // Point closest the view const Float4 nearPointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(nearPoint, 1.0)); float nearDepth = nearPointClip.Z / nearPointClip.W; @@ -700,8 +714,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoi nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f); farDepth = Math::Clamp(farDepth, nearDepth, 1.0f); - // TODO: swap depths when using reversed depth buffer return Float2(nearDepth, farDepth); +#endif } Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere& bounds) @@ -713,6 +727,24 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere& Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span& points) { +#if REVERSE_Z + // Find min and max view depth range for list of points + float nearDepth = view.Far, farDepth = view.Near; + for (int32 i = 0; i < points.Length(); i++) + { + const Float3 viewPoint = Float3::Transform(points[i], view.View); + nearDepth = Math::Min(nearDepth, viewPoint.Z); + farDepth = Math::Max(farDepth, viewPoint.Z); + } + + // Project end points to clip space + Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, nearDepth, 1)); + Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, farDepth, 1)); + clipNearPoint /= clipNearPoint.W; + clipFarPoint /= clipFarPoint.W; + + return Float2(clipNearPoint.Z, clipFarPoint.Z); +#else // Find min and max depth range for list of points float nearDepth = 1.0f, farDepth = 0.0f; for (int32 i = 0; i < points.Length(); i++) @@ -729,8 +761,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span& p nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f); farDepth = Math::Clamp(farDepth, nearDepth, 1.0f); - // TODO: swap depths when using reversed depth buffer return Float2(nearDepth, farDepth); +#endif } Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingBox& bounds) @@ -749,11 +781,21 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const OrientedBoundin float RenderTools::GetDepthBounds(const RenderView& view, const Float3& point, bool near) { +#if REVERSE_Z + Float3 viewPoint = Float3::Transform(point, view.View); + viewPoint.Z = Math::Clamp(viewPoint.Z, view.Near, view.Far); + + Float4 clipPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewPoint.Z, 1)); + clipPoint /= clipPoint.W; + + return clipPoint.Z; +#else const Float4 pointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(point, 1.0)); float depth = pointClip.Z / pointClip.W; if (depth >= 1.0f) depth = near ? 0.0f : 1.0f; // Point is behind the view return Math::Clamp(depth, 0.0f, 1.0f); +#endif } float RenderTools::GetDepthBounds(const RenderView& view, float viewDistance, bool near) diff --git a/Source/Engine/Graphics/RenderTools.h b/Source/Engine/Graphics/RenderTools.h index 8c565eed5..58e867ba3 100644 --- a/Source/Engine/Graphics/RenderTools.h +++ b/Source/Engine/Graphics/RenderTools.h @@ -173,7 +173,12 @@ public: static Float2 GetDepthBounds(const RenderView& view, const OrientedBoundingBox& bounds); static float GetDepthBounds(const RenderView& view, const Float3& point, bool near); static float GetDepthBounds(const RenderView& view, float viewDistance, bool near); - static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f; // Skip background/sky pixels from shading + // Skip background/sky pixels from shading +#if REVERSE_Z + static constexpr float DepthBoundMaxBackground = 0.0000001f; +#else + static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f; +#endif // Calculates error for a given render target format to reduce floating-point precision artifacts via QuantizeColor (from Noise.hlsl). static Float3 GetColorQuantizationError(PixelFormat format); diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 0472ce346..697be453d 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -65,7 +65,11 @@ void RenderView::Prepare(RenderContext& renderContext) void RenderView::PrepareCache(const RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter, const RenderView* mainView) { // The same format used by the Flax common shaders and postFx materials - ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, Far / (Far - Near), (-Far * Near) / (Far - Near) / Far); +#if REVERSE_Z + ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, -Near / (Far - Near), (Far * Near) / (Far - Near) / Far); +#else + ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, Far / (Far - Near), -(Far * Near) / (Far - Near) / Far); +#endif ScreenSize = Float4(width, height, 1.0f / width, 1.0f / height); TemporalAAJitter.Z = TemporalAAJitter.X; diff --git a/Source/Engine/Graphics/Shaders/Cache/ShaderCacheManager.cpp b/Source/Engine/Graphics/Shaders/Cache/ShaderCacheManager.cpp index 8a10b81a9..7fcac839b 100644 --- a/Source/Engine/Graphics/Shaders/Cache/ShaderCacheManager.cpp +++ b/Source/Engine/Graphics/Shaders/Cache/ShaderCacheManager.cpp @@ -188,17 +188,41 @@ bool ShaderCacheManagerService::Init() int32 ShaderCacheVersion = -1; int32 MaterialGraphVersion = -1; int32 ParticleGraphVersion = -1; - bool ShaderDebug; - bool ShaderProfile; - }; - CacheVersion cacheVersion; - const String cacheVerFile = rootDir / TEXT("CacheVersion"); + union + { + struct + { + uint32 ShaderDebug : 1; + uint32 ShaderProfile : 1; + uint32 ReverseZ : 1; + }; + uint32 Flags; + }; + + CacheVersion() + { + Platform::MemoryClear(this, sizeof(*this)); + } + + void InitDefault() + { + EngineVersion = FLAXENGINE_VERSION_BUILD; + ShaderCacheVersion = GPU_SHADER_CACHE_VERSION; + MaterialGraphVersion = MATERIAL_GRAPH_VERSION; + ParticleGraphVersion = PARTICLE_GPU_GRAPH_VERSION; + Flags = 0; #if USE_EDITOR - const bool shaderDebug = CommandLine::Options.ShaderDebug.IsTrue(); - const bool shaderProfile = CommandLine::Options.ShaderProfile.IsTrue(); -#else - const bool shaderDebug = false; + ShaderDebug = CommandLine::Options.ShaderDebug.IsTrue(); + ShaderProfile = CommandLine::Options.ShaderProfile.IsTrue(); #endif +#if REVERSE_Z + ReverseZ = true; +#endif + } + }; + CacheVersion cacheVersion, cacheVersionDefault; + cacheVersionDefault.InitDefault(); + const String cacheVerFile = rootDir / TEXT("CacheVersion"); if (FileSystem::FileExists(cacheVerFile)) { if (File::ReadAllBytes(cacheVerFile, (byte*)&cacheVersion, sizeof(cacheVersion))) @@ -207,34 +231,25 @@ bool ShaderCacheManagerService::Init() LOG(Warning, "Failed to read the shaders cache database version file."); } } - if (cacheVersion.EngineVersion != FLAXENGINE_VERSION_BUILD - || cacheVersion.ShaderCacheVersion != GPU_SHADER_CACHE_VERSION - || cacheVersion.MaterialGraphVersion != MATERIAL_GRAPH_VERSION - || cacheVersion.ParticleGraphVersion != PARTICLE_GPU_GRAPH_VERSION - || cacheVersion.ShaderDebug != shaderDebug - || cacheVersion.ShaderProfile != shaderProfile + if (cacheVersion.EngineVersion != cacheVersionDefault.EngineVersion + || cacheVersion.ShaderCacheVersion != cacheVersionDefault.ShaderCacheVersion + || cacheVersion.MaterialGraphVersion != cacheVersionDefault.MaterialGraphVersion + || cacheVersion.ParticleGraphVersion != cacheVersionDefault.ParticleGraphVersion + || cacheVersion.Flags != cacheVersionDefault.Flags ) { LOG(Warning, "Shaders cache database is invalid. Performing reset."); - if (FileSystem::DirectoryExists(rootDir) && FileSystem::DeleteDirectory(rootDir)) { - LOG(Warning, "Failed to reset the shaders cache database."); + LOG(Warning, "Failed to reset shaders cache database."); } if (FileSystem::CreateDirectory(rootDir)) { - LOG(Error, "Failed to createe the shaders cache database directory."); + LOG(Error, "Failed to create shaders cache database directory."); } - - cacheVersion.EngineVersion = FLAXENGINE_VERSION_BUILD; - cacheVersion.ShaderCacheVersion = GPU_SHADER_CACHE_VERSION; - cacheVersion.MaterialGraphVersion = MATERIAL_GRAPH_VERSION; - cacheVersion.ParticleGraphVersion = PARTICLE_GPU_GRAPH_VERSION; - cacheVersion.ShaderDebug = shaderDebug; - cacheVersion.ShaderProfile = shaderProfile; - if (File::WriteAllBytes(cacheVerFile, (byte*)&cacheVersion, sizeof(cacheVersion))) + if (File::WriteAllBytes(cacheVerFile, (byte*)&cacheVersionDefault, sizeof(cacheVersionDefault))) { - LOG(Error, "Failed to create the shaders cache database version file."); + LOG(Error, "Failed to create shaders cache database version file."); } } diff --git a/Source/Engine/Graphics/Textures/GPUSamplerDescription.h b/Source/Engine/Graphics/Textures/GPUSamplerDescription.h index 90c446a8f..183850e30 100644 --- a/Source/Engine/Graphics/Textures/GPUSamplerDescription.h +++ b/Source/Engine/Graphics/Textures/GPUSamplerDescription.h @@ -47,6 +47,8 @@ API_ENUM() enum class GPUSamplerCompareFunction Never = 0, /// If the source data is less than the destination data, the comparison passes. Less = 1, + /// If the source data is greater than the destination data, the comparison passes. + Greater = 2, API_ENUM(Attributes="HideInEditor") MAX }; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 47a31e109..f581753dc 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -25,6 +25,7 @@ bool EnableNvapi = false; #endif #if COMPILE_WITH_AGS +#define AGS_EXCLUDE_DIRECTX_12 #include #include "Engine/Engine/Globals.h" #include "FlaxEngine.Gen.h" @@ -757,7 +758,11 @@ bool GPUDeviceDX11::Init() samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 1; +#if REVERSE_Z + samplerDesc.ComparisonFunc = D3D11_COMPARISON_GREATER; +#else samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; +#endif // Linear Clamp samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp index 6c9531b8e..23761098a 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp @@ -77,6 +77,9 @@ bool GPUSamplerDX11::OnInit() case GPUSamplerCompareFunction::Less: samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS; break; + case GPUSamplerCompareFunction::Greater: + samplerDesc.ComparisonFunc = D3D11_COMPARISON_GREATER; + break; default: return true; } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 5b201c6e9..aa186ba52 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -155,10 +155,15 @@ RootSignatureDX12::RootSignatureDX12() InitSampler(2, D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_WRAP); // Point Wrap InitSampler(3, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP); +#if REVERSE_Z + auto comparisionFunc = D3D12_COMPARISON_FUNC_GREATER; +#else + auto comparisionFunc = D3D12_COMPARISON_FUNC_LESS; +#endif // Shadow - InitSampler(4, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_COMPARISON_FUNC_LESS_EQUAL); + InitSampler(4, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, comparisionFunc); // Shadow PCF - InitSampler(5, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_COMPARISON_FUNC_LESS_EQUAL); + InitSampler(5, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, comparisionFunc); // Init _desc.NumParameters = ARRAY_COUNT(_parameters); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp index 7c82fd466..1fb108d62 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp @@ -77,6 +77,9 @@ bool GPUSamplerDX12::OnInit() case GPUSamplerCompareFunction::Less: samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS; break; + case GPUSamplerCompareFunction::Greater: + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_GREATER; + break; default: return true; } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp index cc5ad7338..9e827900c 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp @@ -136,7 +136,7 @@ bool GPUTextureDX12::OnInit() else if (useDSV) { clearValue.Format = _dxgiFormatDSV; - clearValue.DepthStencil.Depth = 1.0f; + clearValue.DepthStencil.Depth = GPU_DEPTH_RANGE_MAX; clearValue.DepthStencil.Stencil = 0; clearValuePtr = &clearValue; } diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index 277272181..0aded637a 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -796,9 +796,8 @@ void GPUContextVulkan::OnDrawCall() if (_psDirtyFlag && pipelineState && (_rtDepth || _rtCount)) { _psDirtyFlag = false; - const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer()->GetHandle(); const auto pipeline = pipelineState->GetState(_renderPass, _vertexLayout); - vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); RENDER_STAT_PS_STATE_CHANGE(); if (_depthBoundsEnable && (!_currentState || !_currentState->DepthBoundsEnable)) { diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index ccdb46ac7..bb11d10c8 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -797,7 +797,7 @@ HelperResourcesVulkan::HelperResourcesVulkan(GPUDeviceVulkan* device) Platform::MemoryClear(_staticSamplers, sizeof(_staticSamplers)); } -void InitSampler(VkSamplerCreateInfo& createInfo, bool supportsMirrorClampToEdge, GPUSamplerFilter filter, GPUSamplerAddressMode addressU, GPUSamplerAddressMode addressV, GPUSamplerAddressMode addressW, GPUSamplerCompareFunction compareFunction) +void InitSampler(VkSamplerCreateInfo& createInfo, bool supportsMirrorClampToEdge, GPUSamplerFilter filter, GPUSamplerAddressMode addressU, GPUSamplerAddressMode addressV, GPUSamplerAddressMode addressW, GPUSamplerCompareFunction compareFunction = GPUSamplerCompareFunction::Never) { createInfo.magFilter = RenderToolsVulkan::ToVulkanMagFilterMode(filter); createInfo.minFilter = RenderToolsVulkan::ToVulkanMinFilterMode(filter); @@ -826,27 +826,33 @@ VkSampler* HelperResourcesVulkan::GetStaticSamplers() createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; // Linear Clamp - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Never); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[0])); // Point Clamp - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Never); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[1])); // Linear Wrap - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerCompareFunction::Never); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[2])); // Point Wrap - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerCompareFunction::Never); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap, GPUSamplerAddressMode::Wrap); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[3])); +#if REVERSE_Z + auto comparisionFunc = GPUSamplerCompareFunction::Greater; +#else + auto comparisionFunc = GPUSamplerCompareFunction::Less; +#endif + // Shadow - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Less); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, comparisionFunc); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[4])); // Shadow PCF - InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Less); + InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, comparisionFunc); VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[5])); } return _staticSamplers; diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h index 82167fd6c..d1f3834a0 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h @@ -283,11 +283,14 @@ public: VkCompareOp result; switch (samplerComparisonFunction) { + case GPUSamplerCompareFunction::Never: + result = VK_COMPARE_OP_NEVER; + break; case GPUSamplerCompareFunction::Less: result = VK_COMPARE_OP_LESS; break; - case GPUSamplerCompareFunction::Never: - result = VK_COMPARE_OP_NEVER; + case GPUSamplerCompareFunction::Greater: + result = VK_COMPARE_OP_GREATER; break; default: CRASH; diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUDeviceWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUDeviceWebGPU.cpp index 2b5a2d6ac..85ff85616 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUDeviceWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUDeviceWebGPU.cpp @@ -636,18 +636,22 @@ bool GPUDeviceWebGPU::Init() // Create default resources auto samplerDesc = GPUSamplerDescription::New(); -#define INIT_SAMPLER(slot, filter, addressMode, compare) \ +#define INIT_SAMPLER(slot, filter, addressMode) \ DefaultSamplers[slot] = New(this); \ samplerDesc.Filter = filter; \ samplerDesc.AddressU = samplerDesc.AddressV = samplerDesc.AddressW = addressMode; \ - samplerDesc.ComparisonFunction = compare; \ DefaultSamplers[slot]->Init(samplerDesc) - INIT_SAMPLER(0, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Never); - INIT_SAMPLER(1, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Never); - INIT_SAMPLER(2, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Wrap, GPUSamplerCompareFunction::Never); - INIT_SAMPLER(3, GPUSamplerFilter::Point, GPUSamplerAddressMode::Wrap, GPUSamplerCompareFunction::Never); - INIT_SAMPLER(4, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Less); - INIT_SAMPLER(5, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Less); + INIT_SAMPLER(0, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp); + INIT_SAMPLER(1, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp); + INIT_SAMPLER(2, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Wrap); + INIT_SAMPLER(3, GPUSamplerFilter::Point, GPUSamplerAddressMode::Wrap); +#if REVERSE_Z + samplerDesc.ComparisonFunction = GPUSamplerCompareFunction::Greater; +#else + samplerDesc.ComparisonFunction = GPUSamplerCompareFunction::Less; +#endif + INIT_SAMPLER(4, GPUSamplerFilter::Point, GPUSamplerAddressMode::Clamp); + INIT_SAMPLER(5, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp); #undef INIT_SAMPLER { WGPUBufferDescriptor bufferDesc = WGPU_BUFFER_DESCRIPTOR_INIT; diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUSamplerWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUSamplerWebGPU.cpp index 6e4bb7851..3e5e01b78 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUSamplerWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUSamplerWebGPU.cpp @@ -27,6 +27,8 @@ WGPUCompareFunction ToCompareFunction(GPUSamplerCompareFunction value) return WGPUCompareFunction_Undefined; // Disabled comparision case GPUSamplerCompareFunction::Less: return WGPUCompareFunction_Less; + case GPUSamplerCompareFunction::Greater: + return WGPUCompareFunction_Greater; default: return WGPUCompareFunction_Undefined; } diff --git a/Source/Engine/Level/Actors/Sky.cpp b/Source/Engine/Level/Actors/Sky.cpp index 7354f3bcf..fd95e61d0 100644 --- a/Source/Engine/Level/Actors/Sky.cpp +++ b/Source/Engine/Level/Actors/Sky.cpp @@ -103,7 +103,11 @@ void Sky::Draw(RenderContext& renderContext) psDesc.CullMode = CullMode::Inverted; psDesc.DepthWriteEnable = false; psDesc.DepthClipEnable = false; +#if REVERSE_Z + psDesc.DepthFunc = ComparisonFunc::GreaterEqual; +#else psDesc.DepthFunc = ComparisonFunc::LessEqual; +#endif if (_psSky->Init(psDesc)) { diff --git a/Source/Engine/Renderer/AmbientOcclusionPass.cpp b/Source/Engine/Renderer/AmbientOcclusionPass.cpp index 2766fe465..625eec155 100644 --- a/Source/Engine/Renderer/AmbientOcclusionPass.cpp +++ b/Source/Engine/Renderer/AmbientOcclusionPass.cpp @@ -536,7 +536,7 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext) } // Apply - context->SetDepthBounds(0.0f, RenderTools::GetDepthBounds(renderContext.View, aoSettings.FadeOutDistance, false)); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(GPU_DEPTH_RANGE_MIN, RenderTools::GetDepthBounds(renderContext.View, aoSettings.FadeOutDistance, false))); context->BindSR(SSAO_TEXTURE_SLOT0, m_finalResults->ViewArray()); context->SetViewportAndScissors((float)m_sizeX, (float)m_sizeY); context->SetState(settings.SkipHalfPixels ? _psApplyHalf : _psApply); diff --git a/Source/Engine/Renderer/DepthOfFieldPass.cpp b/Source/Engine/Renderer/DepthOfFieldPass.cpp index 2c3dc36f8..a015d8d82 100644 --- a/Source/Engine/Renderer/DepthOfFieldPass.cpp +++ b/Source/Engine/Renderer/DepthOfFieldPass.cpp @@ -271,8 +271,13 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame, cbData.BokehTargetSize.Y = static_cast(bokehTargetHeight); // TODO: use projection matrix instead of this far and near stuff? +#if REVERSE_Z + cbData.ProjectionAB.X = -nearPlane / (farPlane - nearPlane); + cbData.ProjectionAB.Y = (farPlane * nearPlane) / (farPlane - nearPlane); +#else cbData.ProjectionAB.X = farPlane / (farPlane - nearPlane); - cbData.ProjectionAB.Y = (-farPlane * nearPlane) / (farPlane - nearPlane); + cbData.ProjectionAB.Y = -(farPlane * nearPlane) / (farPlane - nearPlane); +#endif auto cb = shader->GetCB(0); context->UpdateCB(cb, &cbData); diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 785aa970d..14e7ad1c3 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -442,7 +442,10 @@ bool GBufferPass::IsDebugView(ViewMode mode) void GBufferPass::SetInputs(const RenderView& view, ShaderGBufferData& gBuffer) { // GBuffer params: - // ViewInfo : x-1/Projection[0,0] y-1/Projection[1,1] z-(Far / (Far - Near) w-(-Far * Near) / (Far - Near) / Far) + // With reverse Z enabled: + // ViewInfo : x-1/Projection[0,0] y-1/Projection[1,1] z-(-(Near / (Far - Near)) w-((Far * Near) / (Far - Near) / Far) + // Otherwise: + // ViewInfo : x-1/Projection[0,0] y-1/Projection[1,1] z-(Far / (Far - Near)) w-(-(Far * Near) / (Far - Near) / Far) // ScreenSize : x-Width y-Height z-1 / Width w-1 / Height // ViewPos,ViewFar : x,y,z - world space view position w-Far // InvViewMatrix : inverse view matrix (4 rows by 4 columns) diff --git a/Source/Engine/Renderer/LightPass.cpp b/Source/Engine/Renderer/LightPass.cpp index 51461610e..65a7857d4 100644 --- a/Source/Engine/Renderer/LightPass.cpp +++ b/Source/Engine/Renderer/LightPass.cpp @@ -90,7 +90,7 @@ bool LightPass::setupResources() psDesc.CullMode = CullMode::Normal; if (_psLightLocal.Create(psDesc, shader, "PS_LocalLight")) return true; - psDesc.DepthFunc = ComparisonFunc::Greater; + psDesc.DepthFunc = ComparisonFunc::DefaultInv; psDesc.CullMode = CullMode::Inverted; if (_psLightLocalInside.Create(psDesc, shader, "PS_LocalLight")) return true; @@ -107,7 +107,7 @@ bool LightPass::setupResources() psDesc.CullMode = CullMode::Normal; if (_psLightSky->Init(psDesc)) return true; - psDesc.DepthFunc = ComparisonFunc::Greater; + psDesc.DepthFunc = ComparisonFunc::DefaultInv; psDesc.CullMode = CullMode::Inverted; if (_psLightSkyInside->Init(psDesc)) return true; @@ -275,7 +275,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV if (_depthBounds) { Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius)); - context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(minMaxDepth.X, minMaxDepth.Y)); } context->UpdateCB(cb0, &perLight); context->BindCB(0, cb0); @@ -323,7 +323,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV if (_depthBounds) { Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius)); - context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(minMaxDepth.X, minMaxDepth.Y)); } context->UpdateCB(cb0, &perLight); context->BindCB(0, cb0); @@ -357,7 +357,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV // Calculate lighting if (_depthBounds) - context->SetDepthBounds(0.0f, RenderTools::DepthBoundMaxBackground); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(GPU_DEPTH_RANGE_MIN, RenderTools::DepthBoundMaxBackground)); context->UpdateCB(cb0, &perLight); context->BindCB(0, cb0); context->BindCB(1, cb1); @@ -390,7 +390,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV if (_depthBounds) { Float2 minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, light.Radius)); - context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(minMaxDepth.X, minMaxDepth.Y)); } context->UpdateCB(cb0, &perLight); context->BindCB(0, cb0); @@ -403,7 +403,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV // Restore state if (_depthBounds) - context->SetDepthBounds(0, 1); + context->SetDepthBounds(); context->ResetRenderTarget(); context->ResetSR(); context->ResetCB(); diff --git a/Source/Engine/Renderer/ReflectionsPass.cpp b/Source/Engine/Renderer/ReflectionsPass.cpp index 9723b4c30..0de2330a7 100644 --- a/Source/Engine/Renderer/ReflectionsPass.cpp +++ b/Source/Engine/Renderer/ReflectionsPass.cpp @@ -347,7 +347,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light // Setup depth bounds (if device supports it) if (_depthBounds) - context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(minMaxDepth.X, minMaxDepth.Y)); // Pack probe properties buffer probe.SetShaderData(data.PData); @@ -368,7 +368,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light context->UnBindSR(4); context->ResetRenderTarget(); if (_depthBounds) - context->SetDepthBounds(0, 1); + context->SetDepthBounds(); } // Screen Space Reflections pass @@ -417,7 +417,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light if (_depthBounds) { context->SetRenderTarget(depthBufferRTV, lightBuffer); - context->SetDepthBounds(0, RenderTools::DepthBoundMaxBackground); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(GPU_DEPTH_RANGE_MIN, RenderTools::DepthBoundMaxBackground)); } else context->SetRenderTarget(lightBuffer); @@ -430,7 +430,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light context->SetState(_psCombinePass); context->DrawFullscreenTriangle(); if (_depthBounds) - context->SetDepthBounds(0, 1); + context->SetDepthBounds(); } RenderTargetPool::Release(ssrBuffer); diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 3361eed90..a8abfe35f 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -536,7 +536,7 @@ bool ShadowsPass::setupResources() psDesc.CullMode = CullMode::Normal; if (_psShadowPoint.Create(psDesc, shader, psLocalLight)) return true; - psDesc.DepthFunc = ComparisonFunc::Greater; + psDesc.DepthFunc = ComparisonFunc::DefaultInv; psDesc.CullMode = CullMode::Inverted; if (_psShadowPointInside.Create(psDesc, shader, psLocalLight)) return true; @@ -551,7 +551,7 @@ bool ShadowsPass::setupResources() psDesc.CullMode = CullMode::Normal; if (_psShadowSpot.Create(psDesc, shader, psLocalLight, 8)) return true; - psDesc.DepthFunc = ComparisonFunc::Greater; + psDesc.DepthFunc = ComparisonFunc::DefaultInv; psDesc.CullMode = CullMode::Inverted; if (_psShadowSpotInside.Create(psDesc, shader, psLocalLight, 8)) return true; @@ -959,14 +959,14 @@ void ShadowsPass::SetupLight(ShadowsCustomBuffer& shadows, RenderContext& render { Float3 frustumCornersCs[8] = { - Float3(-1.0f, 1.0f, 0.0f), - Float3(1.0f, 1.0f, 0.0f), - Float3(1.0f, -1.0f, 0.0f), - Float3(-1.0f, -1.0f, 0.0f), - Float3(-1.0f, 1.0f, 1.0f), - Float3(1.0f, 1.0f, 1.0f), - Float3(1.0f, -1.0f, 1.0f), - Float3(-1.0f, -1.0f, 1.0f), + Float3(-1.0f, 1.0f, GPU_DEPTH_RANGE_MIN), + Float3(1.0f, 1.0f, GPU_DEPTH_RANGE_MIN), + Float3(1.0f, -1.0f, GPU_DEPTH_RANGE_MIN), + Float3(-1.0f, -1.0f, GPU_DEPTH_RANGE_MIN), + Float3(-1.0f, 1.0f, GPU_DEPTH_RANGE_MAX), + Float3(1.0f, 1.0f, GPU_DEPTH_RANGE_MAX), + Float3(1.0f, -1.0f, GPU_DEPTH_RANGE_MAX), + Float3(-1.0f, -1.0f, GPU_DEPTH_RANGE_MAX), }; Matrix invProjectionMatrix; Matrix::Invert(renderContext.View.NonJitteredProjection, invProjectionMatrix); @@ -1139,7 +1139,7 @@ void ShadowsPass::SetupLight(ShadowsCustomBuffer& shadows, RenderContext& render void ShadowsPass::ClearShadowMapTile(GPUContext* context, GPUConstantBuffer* quadShaderCB, QuadShaderData& quadShaderData) const { // Color.r is used by PS_DepthClear in Quad shader to clear depth - quadShaderData.Color = Float4::One; + quadShaderData.Color = GPU_DEPTH_RANGE_MAX; context->UpdateCB(quadShaderCB, &quadShaderData); context->BindCB(0, quadShaderCB); @@ -1590,14 +1590,7 @@ void ShadowsPass::RenderShadowMaps(RenderContextBatch& renderContextBatch) context->SetViewportAndScissors(Viewport(tile.StaticRectTile->X, tile.StaticRectTile->Y, tile.StaticRectTile->Width, tile.StaticRectTile->Height)); if (!shadows.ClearStaticShadowMapAtlas) { - // Color.r is used by PS_DepthClear in Quad shader to clear depth - quadShaderData.Color = Float4::One; - context->UpdateCB(quadShaderCB, &quadShaderData); - context->BindCB(0, quadShaderCB); - - // Clear tile depth - context->SetState(_psDepthClear); - context->DrawFullscreenTriangle(); + ClearShadowMapTile(context, quadShaderCB, quadShaderData); } // Draw objects depth @@ -1748,8 +1741,8 @@ void ShadowsPass::RenderShadowMask(RenderContextBatch& renderContextBatch, Rende if (light.IsPointLight || light.IsSpotLight) minMaxDepth = RenderTools::GetDepthBounds(view, BoundingSphere(light.Position, ((RenderLocalLightData&)light).Radius)); else //if (light.IsDirectionalLight) - minMaxDepth = Float2(0.0f, RenderTools::DepthBoundMaxBackground); - context->SetDepthBounds(minMaxDepth.X, minMaxDepth.Y); + minMaxDepth = Float2(GPU_DEPTH_RANGE_MIN, RenderTools::DepthBoundMaxBackground); + context->SetDepthBounds(GPU_DEPTH_RANGE_BOUNDS(minMaxDepth.X, minMaxDepth.Y)); } if (light.IsPointLight) { diff --git a/Source/Engine/ShadersCompilation/ShaderCompiler.cpp b/Source/Engine/ShadersCompilation/ShaderCompiler.cpp index cfb08b925..4b46a960f 100644 --- a/Source/Engine/ShadersCompilation/ShaderCompiler.cpp +++ b/Source/Engine/ShadersCompilation/ShaderCompiler.cpp @@ -249,6 +249,9 @@ bool ShaderCompiler::OnCompileBegin() const auto profile = GetProfile(); const auto featureLevel = RenderTools::GetFeatureLevel(profile); _globalMacros.Add({ "FEATURE_LEVEL", Numbers[(int32)featureLevel] }); +#if REVERSE_Z + _globalMacros.Add({ "REVERSE_Z", "1"}); +#endif return false; } diff --git a/Source/Shaders/BakeLightmap.shader b/Source/Shaders/BakeLightmap.shader index c9b8db308..3c101f6a5 100644 --- a/Source/Shaders/BakeLightmap.shader +++ b/Source/Shaders/BakeLightmap.shader @@ -60,7 +60,7 @@ RenderCacheVSOutput VS_RenderCacheModel(ModelInput input) float2 lightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy; lightmapUV.y = 1.0 - lightmapUV.y; lightmapUV.xy = lightmapUV.xy * 2.0 - 1.0; - output.Position = float4(lightmapUV, 0, 1); + output.Position = float4(lightmapUV, DEPTH_RANGE_MIN, 1); return output; } @@ -129,7 +129,7 @@ RenderCacheVSOutput VS_RenderCacheTerrain(TerrainVertexInput input) float2 lightmapUV = input.TexCoord * LightmapArea.zw + LightmapArea.xy; lightmapUV.y = 1.0 - lightmapUV.y; lightmapUV.xy = lightmapUV.xy * 2.0 - 1.0; - output.Position = float4(lightmapUV, 0, 1); + output.Position = float4(lightmapUV, DEPTH_RANGE_MIN, 1); return output; } diff --git a/Source/Shaders/ColorGrading.shader b/Source/Shaders/ColorGrading.shader index 3d80b3e33..e4ea1c847 100644 --- a/Source/Shaders/ColorGrading.shader +++ b/Source/Shaders/ColorGrading.shader @@ -317,7 +317,7 @@ Quad_VS2GS VS_WriteToSlice(float2 position : POSITION0, float2 texCoord : TEXCOO #if VULKAN position.y = position.y * -1.0f; #endif - output.Vertex.Position = float4(position, 0, 1); + output.Vertex.Position = float4(position, DEPTH_RANGE_MIN, 1); output.Vertex.TexCoord = texCoord; output.LayerIndex = layerIndex; return output; diff --git a/Source/Shaders/Common.hlsl b/Source/Shaders/Common.hlsl index 457999398..3360f0380 100644 --- a/Source/Shaders/Common.hlsl +++ b/Source/Shaders/Common.hlsl @@ -4,22 +4,40 @@ #define __COMMON__ // Platform macros -#if !defined(DIRECTX) +#ifndef DIRECTX #define DIRECTX 0 #endif -#if !defined(OPENGL) +#ifndef OPENGL #define OPENGL 0 #endif -#if !defined(VULKAN) +#ifndef VULKAN #define VULKAN 0 #endif -#if defined(PLATFORM_PS4) +#ifdef PLATFORM_PS4 #include "./FlaxPlatforms/PS4/Shaders/PS4Common.hlsl" #endif -#if defined(PLATFORM_PS5) +#ifdef PLATFORM_PS5 #include "./FlaxPlatforms/PS5/Shaders/PS5Common.hlsl" #endif +// Reversed Z support +#ifndef REVERSE_Z +#define REVERSE_Z 0 +#endif +#if REVERSE_Z +#define DEPTH_RANGE_MIN 1 +#define DEPTH_RANGE_MAX 0 +#define DEPTH_CMP(l, r) (l > r) +#define DEPTH_DIFF(l, r) (r - l) +#define DEPTH_01(d) (1 - d) +#else +#define DEPTH_RANGE_MIN 0 +#define DEPTH_RANGE_MAX 1 +#define DEPTH_CMP(l, r) (l < r) +#define DEPTH_DIFF(l, r) (l - r) +#define DEPTH_01(d) (d) +#endif + // Feature levels #define FEATURE_LEVEL_ES2 0 #define FEATURE_LEVEL_ES3 1 @@ -157,15 +175,20 @@ float4 LoadTextureWGSL(Texture2D tex, float2 uv) #else #define SAMPLE_RT_DEPTH(rt, texCoord) SAMPLE_RT(rt, texCoord).r #endif + +// General purpose constants #define HDR_CLAMP_MAX 65472.0 #define PI 3.1415926535897932 #define UNITS_TO_METERS_SCALE 0.01f -#define REVERSE_Z 0 // Structure that contains information about GBuffer struct GBufferData { - float4 ViewInfo; // x-1/Projection[0,0], y-1/Projection[1,1], z-(Far / (Far - Near), w-(-Far * Near) / (Far - Near) / Far) + // If reverse Z enabled: + // x-1/Projection[0,0], y-1/Projection[1,1], z-(-Near / (Far - Near)), w-((Far * Near) / (Far - Near) / Far) + // Otherwise: + // x-1/Projection[0,0], y-1/Projection[1,1], z-(Far / (Far - Near)), w-(-(Far * Near) / (Far - Near) / Far) + float4 ViewInfo; float4 ScreenSize; // x-Width, y-Height, z-1/Width, w-1/Height float3 ViewPos; // view position (in world space) float ViewFar; // view far plane distance (in world space) diff --git a/Source/Shaders/DebugDraw.shader b/Source/Shaders/DebugDraw.shader index 4f1aa9ba5..62576dd17 100644 --- a/Source/Shaders/DebugDraw.shader +++ b/Source/Shaders/DebugDraw.shader @@ -41,7 +41,7 @@ float4 PS(VS2PS input) : SV_Target { float sceneDepthDeviceZ = SceneDepthTexture.Load(int3(input.Position.xy, 0)).r; float interpolatedDeviceZ = input.Position.z; - clip(sceneDepthDeviceZ - interpolatedDeviceZ); + clip(DEPTH_DIFF(sceneDepthDeviceZ, interpolatedDeviceZ)); } #endif diff --git a/Source/Shaders/GBuffer.shader b/Source/Shaders/GBuffer.shader index e9b241111..50478e2c9 100644 --- a/Source/Shaders/GBuffer.shader +++ b/Source/Shaders/GBuffer.shader @@ -59,7 +59,7 @@ float4 PS_DebugView(Quad_VS2PS input) : SV_Target { case View_Mode_Diffuse: result = gBuffer.Color; break; case View_Mode_Normals: result = gBuffer.Normal * 0.5 + 0.5; break; - case View_Mode_Depth: result = gBuffer.ViewPos.z / GBuffer.ViewFar; break; + case View_Mode_Depth: result = pow(gBuffer.ViewPos.z / GBuffer.ViewFar, 0.6); break; case View_Mode_AmbientOcclusion: result = gBuffer.AO; break; case View_Mode_Metalness: result = gBuffer.Metalness; break; case View_Mode_Rougness: result = gBuffer.Roughness; break; diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl b/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl index 6594f58c0..86cf114ae 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl @@ -147,7 +147,7 @@ float4 SampleGlobalSurfaceAtlasTile(const GlobalSurfaceAtlasData data, GlobalSur // Calculate bilinear weights float2 bilinearWeightsUV = frac(atlasUV * data.Resolution + 0.5f); float4 bilinearWeights; - bilinearWeights.x = (1.0 - bilinearWeightsUV.x) * (bilinearWeightsUV.y); + bilinearWeights.x = (1 - bilinearWeightsUV.x) * (bilinearWeightsUV.y); bilinearWeights.y = (bilinearWeightsUV.x) * (bilinearWeightsUV.y); bilinearWeights.z = (bilinearWeightsUV.x) * (1 - bilinearWeightsUV.y); bilinearWeights.w = (1 - bilinearWeightsUV.x) * (1 - bilinearWeightsUV.y); @@ -159,8 +159,9 @@ float4 SampleGlobalSurfaceAtlasTile(const GlobalSurfaceAtlasData data, GlobalSur UNROLL for (uint i = 0; i < 4; i++) { - depthVisibility[i] = 1.0f - saturate((abs(tileDepth - tileZ[i]) - depthThreshold) / (0.5f * depthThreshold)); - if (tileZ[i] >= 1.0f) + float z = DEPTH_01(tileZ[i]); + depthVisibility[i] = 1.0f - saturate((abs(tileDepth - z) - depthThreshold) / (0.5f * depthThreshold)); + if (z >= 1.0f) depthVisibility[i] = 0.0f; } float sampleWeight = dot(depthVisibility, bilinearWeights); diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.shader b/Source/Shaders/GI/GlobalSurfaceAtlas.shader index 76af07634..716d63352 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.shader +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.shader @@ -43,7 +43,7 @@ META_VS(true, FEATURE_LEVEL_SM5) AtlasVertexOutput VS_Atlas(AtlasVertexInput input) { AtlasVertexOutput output; - output.Position = float4(input.Position, 1, 1); + output.Position = float4(input.Position, DEPTH_RANGE_MAX, 1); output.TileUV = input.TileUV; output.TileAddress = input.TileAddress; return output; @@ -143,7 +143,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target } // Reconstruct world-space position manually (from uv+depth within a tile) - float tileDepth = SampleZ(atlasUV); + float tileDepth = DEPTH_01(SampleZ(atlasUV)); float3 tileSpacePos = float3(input.TileUV.x - 0.5f, 0.5f - input.TileUV.y, tileDepth); float3 gBufferTilePos = tileSpacePos * tile.ViewBoundsSize; float4x4 tileLocalToWorld = Inverse(tile.WorldToLocal); diff --git a/Source/Shaders/GUI.shader b/Source/Shaders/GUI.shader index dfce289e3..35a79210d 100644 --- a/Source/Shaders/GUI.shader +++ b/Source/Shaders/GUI.shader @@ -31,7 +31,7 @@ VS2PS VS(Render2DVertex input) if ((int)input.CustomDataAndClipOrigin.y & RENDER2D_FEATURE_VERTEX_SNAPPING) input.Position = (float2)(int2)input.Position; - output.Position = PROJECT_POINT(float4(input.Position, 0, 1), ViewProjection); + output.Position = PROJECT_POINT(float4(input.Position, DEPTH_RANGE_MIN, 1), ViewProjection); output.Color = input.Color; output.TexCoord = input.TexCoord; output.ClipOriginAndPos = float4(input.CustomDataAndClipOrigin.zw, input.Position); @@ -126,7 +126,7 @@ float4 PS_Downscale(Quad_VS2PS input) : SV_Target0 { float2 boundsPos = input.TexCoord * Bounds.zw + Bounds.xy; - float4 clipPos = PROJECT_POINT(float4(boundsPos, 0, 1), ViewProjection); + float4 clipPos = PROJECT_POINT(float4(boundsPos, DEPTH_RANGE_MIN, 1), ViewProjection); clipPos.xy /= clipPos.w; float2 uvPos = ClipToUv(clipPos.xy); diff --git a/Source/Shaders/MultiScaler.shader b/Source/Shaders/MultiScaler.shader index 828483198..bf0c231c7 100644 --- a/Source/Shaders/MultiScaler.shader +++ b/Source/Shaders/MultiScaler.shader @@ -28,11 +28,19 @@ float PS_HalfDepth(Quad_VS2PS input) // Load 4 depth values (2x2 quad) float4 depths = TextureGatherDepth(Input, input.TexCoord); +#if REVERSE_Z +#if HZB_CLOSEST + return max(depths.x, max(depths.y, max(depths.z, depths.w))); +#else + return min(depths.x, min(depths.y, min(depths.z, depths.w))); +#endif +#else #if HZB_CLOSEST return min(depths.x, min(depths.y, min(depths.z, depths.w))); #else return max(depths.x, max(depths.y, max(depths.z, depths.w))); #endif +#endif } // Pixel Shader for 5-tap gaussian blur diff --git a/Source/Shaders/Quad.shader b/Source/Shaders/Quad.shader index 815649ec8..0b318c863 100644 --- a/Source/Shaders/Quad.shader +++ b/Source/Shaders/Quad.shader @@ -19,7 +19,7 @@ META_VS(true, FEATURE_LEVEL_ES2) Quad_VS2PS VS(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0) { Quad_VS2PS output; - output.Position = float4(Position, 0, 1); + output.Position = float4(Position, DEPTH_RANGE_MIN, 1); output.TexCoord = TexCoord; return output; } @@ -29,7 +29,7 @@ META_VS(true, FEATURE_LEVEL_ES2) MaterialVertexOutput VS_PostFx(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0) { MaterialVertexOutput output; - output.Position = float4(Position, 0, 1); + output.Position = float4(Position, DEPTH_RANGE_MIN, 1); output.WorldPosition = output.Position.xyz; output.TexCoord = TexCoord; return output; diff --git a/Source/Shaders/SMAA.shader b/Source/Shaders/SMAA.shader index 5b40ab162..00139982a 100644 --- a/Source/Shaders/SMAA.shader +++ b/Source/Shaders/SMAA.shader @@ -1127,7 +1127,7 @@ META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) VaryingsEdge VS_Edge(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0) { VaryingsEdge output; - output.Position = float4(Position, 0, 1); + output.Position = float4(Position, DEPTH_RANGE_MIN, 1); output.TexCoord = TexCoord; SMAAEdgeDetectionVS(TexCoord, output.Offsets); return output; @@ -1162,7 +1162,7 @@ META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) VaryingsBlend VS_Blend(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0) { VaryingsBlend output; - output.Position = float4(Position.xy, 0, 1); + output.Position = float4(Position.xy, DEPTH_RANGE_MIN, 1); output.TexCoord = TexCoord; output.PixCoord = output.TexCoord * SMAA_RT_METRICS.zw; SMAABlendingWeightCalculationVS(TexCoord, output.PixCoord, output.Offsets); @@ -1204,7 +1204,7 @@ META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) VaryingsNeighbor VS_Neighbor(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0) { VaryingsNeighbor output; - output.Position = float4(Position, 0, 1); + output.Position = float4(Position, DEPTH_RANGE_MIN, 1); output.TexCoord = TexCoord; SMAANeighborhoodBlendingVS(TexCoord, output.Offset); return output; diff --git a/Source/Shaders/SSR.hlsl b/Source/Shaders/SSR.hlsl index a5f6679b1..bc934b1bf 100644 --- a/Source/Shaders/SSR.hlsl +++ b/Source/Shaders/SSR.hlsl @@ -6,6 +6,9 @@ #include "./Flax/MonteCarlo.hlsl" #include "./Flax/GBufferCommon.hlsl" #if SSR_USE_HZB +#if REVERSE_Z +#define FFX_SSSR_INVERTED_DEPTH_RANGE 1 +#endif #include "./FlaxThirdParty/FidelityFX/ffx_sssr.h" #endif @@ -117,7 +120,7 @@ float3 TraceScreenSpaceReflection( { // Sample depth buffer and calculate depth difference float currSample = SAMPLE_RT_DEPTH(depthBuffer, currOffset.xy); - float depthDiff = currOffset.z - currSample; + float depthDiff = DEPTH_DIFF(currOffset.z, currSample); // Check intersection if (depthDiff >= 0) diff --git a/Source/Shaders/Shadows.shader b/Source/Shaders/Shadows.shader index 275048333..1334a9108 100644 --- a/Source/Shaders/Shadows.shader +++ b/Source/Shaders/Shadows.shader @@ -47,7 +47,7 @@ float RayCastScreenSpaceShadow(GBufferData gBufferData, GBufferSample gBuffer, f float3 rayUV = rayCS.xyz / rayCS.w; rayUV.xy = rayUV.xy * float2(0.5, -0.5) + float2(0.5, 0.5); float sceneDepth = SampleDepth(gBufferData, rayUV.xy) * gBufferData.ViewFar; - float rayDepth = (gBufferData.ViewInfo.w / (rayUV.z - gBufferData.ViewInfo.z)) * gBufferData.ViewFar * 0.998; + float rayDepth = LinearizeZ(gBufferData, rayUV.z) * gBufferData.ViewFar * 0.998; float surfaceThickness = 0.035f + rayDepth * rayLength; float depthTestHardness = 0.005f; float lightAmount = saturate((rayDepth - sceneDepth) / depthTestHardness) * saturate((sceneDepth + surfaceThickness - rayDepth) / depthTestHardness); diff --git a/Source/Shaders/ShadowsCommon.hlsl b/Source/Shaders/ShadowsCommon.hlsl index f3ff9fd5b..229a0697f 100644 --- a/Source/Shaders/ShadowsCommon.hlsl +++ b/Source/Shaders/ShadowsCommon.hlsl @@ -74,9 +74,13 @@ float3 GetShadowPositionOffset(float offsetScale, float NoL, float3 normal) float CalculateSubsurfaceOcclusion(float opacity, float sceneDepth, float shadowMapDepth) { - float thickness = max(sceneDepth - shadowMapDepth, 0); + float thickness = max(DEPTH_DIFF(sceneDepth, shadowMapDepth), 0); float occlusion = 1 - saturate(thickness * lerp(1.0f, 100.0f, opacity)); +#if REVERSE_Z + return shadowMapDepth < 0.01f ? 1 : occlusion; +#else return shadowMapDepth > 0.99f ? 1 : occlusion; +#endif } float PostProcessShadow(ShadowData lightShadow, float shadow) diff --git a/Source/Shaders/ShadowsSampling.hlsl b/Source/Shaders/ShadowsSampling.hlsl index 029085429..8a1b6fb1f 100644 --- a/Source/Shaders/ShadowsSampling.hlsl +++ b/Source/Shaders/ShadowsSampling.hlsl @@ -24,8 +24,8 @@ #define SAMPLE_SHADOW_MAP(shadowMap, shadowUV, sceneDepth) shadowMap.SampleCmpLevelZero(ShadowSamplerLinear, shadowUV, sceneDepth) #define SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowUV, texelOffset, sceneDepth) shadowMap.SampleCmpLevelZero(ShadowSamplerLinear, shadowUV, sceneDepth, texelOffset) #else -#define SAMPLE_SHADOW_MAP(shadowMap, shadowUV, sceneDepth) (sceneDepth < shadowMap.SampleLevel(SamplerLinearClamp, shadowUV, 0).r) -#define SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowUV, texelOffset, sceneDepth) (sceneDepth < shadowMap.SampleLevel(SamplerLinearClamp, shadowUV, 0, texelOffset).r) +#define SAMPLE_SHADOW_MAP(shadowMap, shadowUV, sceneDepth) DEPTH_CMP(sceneDepth, shadowMap.SampleLevel(SamplerLinearClamp, shadowUV, 0).r) +#define SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowUV, texelOffset, sceneDepth) (sceneDepth, shadowMap.SampleLevel(SamplerLinearClamp, shadowUV, 0, texelOffset).r) #endif #if defined(WGSL) #define LOAD_SHADOW_MAP(shadowMap, shadowUV) SAMPLE_RT_DEPTH(shadowMap, shadowUV) @@ -60,7 +60,11 @@ float2 GetLightShadowAtlasUV(ShadowData shadow, ShadowTileData shadowTile, float { // Project into shadow space (WorldToShadow is pre-multiplied to convert Clip Space to UV Space) shadowPosition = mul(float4(samplePosition, 1.0f), shadowTile.WorldToShadow); +#if REVERSE_Z + shadowPosition.z += shadow.Bias; +#else shadowPosition.z -= shadow.Bias; +#endif shadowPosition.xyz /= shadowPosition.w; // UV Space -> Atlas Tile UV Space @@ -311,7 +315,12 @@ float SampleShadowMapPCSS(Texture2D shadowMap, float2 shadowMapUV, float sincos(rotationAngle, rotation.x, rotation.y); // Search blockers +#if REVERSE_Z + float sceneDepthRev = 1 - sceneDepth; + float searchRadius = sourceAngle * saturate(sceneDepthRev - 0.02f) / sceneDepthRev; +#else float searchRadius = sourceAngle * saturate(sceneDepth - 0.02f) / sceneDepth; +#endif searchRadius = max(searchRadius, minRadius); uint blockers = 0; float avgBlockerDistance = 0.0f; @@ -322,7 +331,7 @@ float SampleShadowMapPCSS(Texture2D shadowMap, float2 shadowMapUV, float offset = shadowMapUV + offset; offset = clamp(offset, uvMin, uvMax); float shadowMapDepth = LOAD_SHADOW_MAP(shadowMap, offset); - if (shadowMapDepth < sceneDepth) + if (DEPTH_CMP(shadowMapDepth, sceneDepth)) { blockers++; avgBlockerDistance += shadowMapDepth; @@ -333,9 +342,14 @@ float SampleShadowMapPCSS(Texture2D shadowMap, float2 shadowMapUV, float avgBlockerDistance /= blockers; // Calculate penumbra size - float penumbra = max(sceneDepth - avgBlockerDistance, 0.0); -#if defined(VULKAN) - sceneDepth *= lerp(1, 0.985f, saturate(penumbra * 4.0f)); // Fix shadow bias issues on Vulkan + float penumbra = max(DEPTH_DIFF(sceneDepth, avgBlockerDistance), 0.0); +#if VULKAN + // Fix shadow bias issues on Vulkan +#if REVERSE_Z + sceneDepth *= lerp(1, 1.025f, saturate(penumbra * 4.0f)); +#else + sceneDepth *= lerp(1, 0.985f, saturate(penumbra * 4.0f)); +#endif #endif float filterRadius = penumbra * sourceAngle; filterRadius = max(filterRadius, minRadius); // Don't use too small filter near blockers to avoid jagged edges @@ -348,7 +362,11 @@ float SampleShadowMapPCSS(Texture2D shadowMap, float2 shadowMapUV, float offset = SampleShadowPCSSRotate(offset, rotation); offset = shadowMapUV + offset; offset = clamp(offset, uvMin, uvMax); +#if REVERSE_Z + shadow += LOAD_SHADOW_MAP(shadowMap, offset) < sceneDepth; +#else shadow += LOAD_SHADOW_MAP(shadowMap, offset) > sceneDepth; +#endif } return shadow / (float)SHADOWS_PCSS_SAMPLES; } diff --git a/Source/ThirdParty/FidelityFX/ffx_sssr.h b/Source/ThirdParty/FidelityFX/ffx_sssr.h index e708d2327..b57238ae9 100644 --- a/Source/ThirdParty/FidelityFX/ffx_sssr.h +++ b/Source/ThirdParty/FidelityFX/ffx_sssr.h @@ -111,7 +111,12 @@ float3 FFX_SSSR_HierarchicalRaymarch(Texture2D depthBuffer, uint hzbMips, float while (i < max_traversal_intersections && current_mip >= most_detailed_mip) { float2 current_mip_position = current_mip_resolution * position.xy; float surface_z = depthBuffer.Load(int3(current_mip_position, current_mip)).x; - if (position.z - surface_z > depthDiffError) overDiffError++; // Count number of times we were under the depth by more than the allowed error +#ifdef FFX_SSSR_INVERTED_DEPTH_RANGE + // Count number of times we were under the depth by more than the allowed error + if (surface_z - position.z > depthDiffError) overDiffError++; +#else + if (position.z - surface_z > depthDiffError) overDiffError++; +#endif bool skipped_tile = FFX_SSSR_AdvanceRay(origin, direction, inv_direction, current_mip_position, current_mip_resolution_inv, floor_offset, uv_offset, surface_z, position, current_t); ++i; if (!skipped_tile || current_mip < (int)hzbMips) // Never go too low depth resolution to avoid blocky artifacts diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index a2016c8cb..d5fc92093 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -412,9 +412,9 @@ namespace Flax.Build.Bindings { currentParam.Name = token.Value; } - // Support nameless arguments. assume optional usage else { + // Support nameless arguments (assumes optional usage) context.Tokenizer.PreviousToken(); if (string.IsNullOrEmpty(currentParam.Attributes)) currentParam.Attributes = "Optional"; @@ -475,6 +475,8 @@ namespace Flax.Build.Bindings // Check for end or next param token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.Comma, TokenType.RightParent }); + if (currentParam.DefaultValue != null && context.PreprocessorDefines.TryGetValue(currentParam.DefaultValue, out var define)) + currentParam.DefaultValue = define; // Default value wrapped into preprocessor define (can be conditional) if (token.Type == TokenType.Comma) { parameters.Add(currentParam); @@ -1216,6 +1218,7 @@ namespace Flax.Build.Bindings token = context.Tokenizer.NextToken(); if (token.Type == TokenType.Equal) { + // Rean enum value token = context.Tokenizer.NextToken(); entry.Value = string.Empty; while (token.Type != TokenType.EndOfFile && @@ -1225,6 +1228,10 @@ namespace Flax.Build.Bindings entry.Value += token.Value; token = context.Tokenizer.NextToken(true); } + + // Optionally swap with preprocessor define + if (context.PreprocessorDefines.TryGetValue(entry.Value, out var define)) + entry.Value = define; } context.Tokenizer.PreviousToken(); diff --git a/Source/Tools/Flax.Build/Build/ProjectTarget.cs b/Source/Tools/Flax.Build/Build/ProjectTarget.cs index f67139a86..42ff62924 100644 --- a/Source/Tools/Flax.Build/Build/ProjectTarget.cs +++ b/Source/Tools/Flax.Build/Build/ProjectTarget.cs @@ -88,6 +88,11 @@ namespace Flax.Build options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_SDL"); options.ScriptingAPI.Defines.Add("PLATFORM_SDL"); } + if (EngineConfiguration.WithReverseZ(options)) + { + options.CompileEnv.PreprocessorDefinitions.Add("REVERSE_Z"); + options.ScriptingAPI.Defines.Add("REVERSE_Z"); + } // Add include paths for this and all referenced projects sources foreach (var project in Project.GetAllProjects()) diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index 8a662df10..e9da81cae 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -306,6 +306,12 @@ namespace Flax.Build [CommandLine("useLargeWorlds", "1 to enable large worlds with 64-bit coordinates precision support in build (USE_LARGE_WORLDS=1)")] public static bool UseLargeWorlds = false; + /// + /// 1 to use reversed Z Buffer, or traditional one. + /// + [CommandLine("useReverseZ", "1 to use reversed Z Buffer, or traditional one.")] + public static bool UseReverseZ = false; + /// /// True if managed C# scripting should be enabled, otherwise false. Engine without C# is partially supported and can be used when porting to a new platform before implementing C# runtime on it. /// @@ -343,6 +349,12 @@ namespace Flax.Build return UseLargeWorlds; } + public static bool WithReverseZ(NativeCpp.BuildOptions options) + { + // Whether to use traditional z-buffer or reversed depth + return UseReverseZ; + } + public static bool WithDotNet(NativeCpp.BuildOptions options) { return UseDotNet;