Merge branch 'HydrogenC-reverse-z' into 1.13
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-1
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user