Merge branch 'HydrogenC-reverse-z' into 1.13

This commit is contained in:
2026-05-12 17:07:50 +02:00
72 changed files with 462 additions and 186 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -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,
@@ -50,6 +50,10 @@
#endif
#include "FlaxEngine.Gen.h"
#ifndef REVERSE_Z
#define REVERSE_Z 0
#endif
Dictionary<String, CookAssetsStep::ProcessAssetFunc> 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;
@@ -97,6 +97,7 @@ public:
{
bool ShadersNoOptimize;
bool ShadersGenerateDebugData;
bool ShadersReverseZ;
Guid StreamingSettingsAssetId;
int32 ShadersVersion;
int32 MaterialGraphVersion;
+1 -5
View File
@@ -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
+8 -3
View File
@@ -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);
@@ -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
@@ -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)
+14 -4
View File
@@ -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)
+22 -7
View File
@@ -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
}
/// <summary>
@@ -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
/// <param name="result">When the method completes, contains the created projection matrix.</param>
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
};
}
+5 -7
View File
@@ -296,15 +296,13 @@ namespace FlaxEngine
/// <summary>
/// Converts a screen space point into a corresponding point in world space.
/// </summary>
/// <param name="source">The vector to project.</param>
/// <param name="source">The vector to project, screen uv and device depth.</param>
/// <param name="projection">The projection matrix.</param>
/// <param name="view">The view matrix.</param>
/// <param name="world">The world matrix.</param>
/// <returns>The unprojected Vector.</returns>
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
/// <summary>
/// Converts a screen space point into a corresponding point in world space.
/// </summary>
/// <param name="source">The vector to project.</param>
/// <param name="matrix">An inverted combined WorldViewProjection matrix.</param>
/// <param name="source">The vector to project, screen uv and device depth.</param>
/// <param name="matrix">An inverted combined ViewProjection matrix.</param>
/// <param name="vector">The unprojected vector.</param>
public void Unproject(ref Vector3 source, ref Matrix matrix, out Vector3 vector)
{
+24 -1
View File
@@ -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
/// <summary>
/// Comparison function modes
/// </summary>
@@ -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
/// <summary>
/// Rendering quality levels.
/// </summary>
+13 -2
View File
@@ -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:
/// <param name="depthBuffer">The depth buffer to clear.</param>
/// <param name="depthValue">The clear depth value.</param>
/// <param name="stencilValue">The clear stencil value.</param>
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;
/// <summary>
/// Clears an unordered access buffer with a float value.
@@ -628,9 +638,10 @@ public:
/// <summary>
/// Sets the minimum and maximum depth values for depth bounds test.
/// </summary>
/// <remarks>Both values must be between 0.0 and 1.0, MinDepth must be less than or equal to MaxDepth.</remarks>
/// <param name="minDepth">The minimum value for depth bound test.</param>
/// <param name="maxDepth">The maximum value for depth bound test.</param>
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:
/// <summary>
+3 -3
View File
@@ -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
@@ -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;
@@ -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);
@@ -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;
@@ -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;
+44 -2
View File
@@ -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<Float3>& 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<Float3>& 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)
+6 -1
View File
@@ -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);
+5 -1
View File
@@ -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;
@@ -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.");
}
}
@@ -47,6 +47,8 @@ API_ENUM() enum class GPUSamplerCompareFunction
Never = 0,
/// <summary>If the source data is less than the destination data, the comparison passes.</summary>
Less = 1,
/// <summary>If the source data is greater than the destination data, the comparison passes.</summary>
Greater = 2,
API_ENUM(Attributes="HideInEditor") MAX
};
@@ -25,6 +25,7 @@
bool EnableNvapi = false;
#endif
#if COMPILE_WITH_AGS
#define AGS_EXCLUDE_DIRECTX_12
#include <ThirdParty/AGS/amd_ags.h>
#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;
@@ -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;
}
@@ -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);
@@ -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;
}
@@ -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;
}
@@ -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))
{
@@ -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;
@@ -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;
@@ -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<GPUSamplerWebGPU>(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;
@@ -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;
}
+4
View File
@@ -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))
{
@@ -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);
+6 -1
View File
@@ -271,8 +271,13 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
cbData.BokehTargetSize.Y = static_cast<float>(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);
+4 -1
View File
@@ -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)
+7 -7
View File
@@ -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();
+4 -4
View File
@@ -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);
+14 -21
View File
@@ -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)
{
@@ -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;
}
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+30 -7
View File
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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;
+4 -3
View File
@@ -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);
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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);
+8
View File
@@ -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
+2 -2
View File
@@ -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;
+3 -3
View File
@@ -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;
+4 -1
View File
@@ -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)
+1 -1
View File
@@ -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);
+5 -1
View File
@@ -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)
+24 -6
View File
@@ -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<float> 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<float> 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<float> 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<float> 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;
}
+6 -1
View File
@@ -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
@@ -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();
@@ -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())
+12
View File
@@ -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;
/// <summary>
/// 1 to use reversed Z Buffer, or traditional one.
/// </summary>
[CommandLine("useReverseZ", "1 to use reversed Z Buffer, or traditional one.")]
public static bool UseReverseZ = false;
/// <summary>
/// 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.
/// </summary>
@@ -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;