Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement custom depth pass rendering. #2378

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions Content/Shaders/GBuffer.flax
Git LFS file not shown
14 changes: 12 additions & 2 deletions Source/Editor/Viewport/EditorViewport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1910,6 +1910,7 @@ public ViewModeOptions(string name, ViewModeOptions[] options)
new ViewModeOptions(ViewMode.LightBuffer, "Light Buffer"),
new ViewModeOptions(ViewMode.Reflections, "Reflections Buffer"),
new ViewModeOptions(ViewMode.Depth, "Depth Buffer"),
new ViewModeOptions(ViewMode.CustomDepth, "Custom Depth Buffer"),
new ViewModeOptions("GBuffer", new[]
{
new ViewModeOptions(ViewMode.Diffuse, "Diffuse"),
Expand Down Expand Up @@ -1956,8 +1957,17 @@ private void WidgetViewModeShowHide(Control cm)
var ccm = (ContextMenu)cm;
foreach (var e in ccm.Items)
{
if (e is ContextMenuButton b && b.Tag is ViewMode v)
b.Icon = Task.ViewMode == v ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
if (e is not ContextMenuButton b)
continue;

if (b.Tag is not ViewMode v)
continue;

b.Icon = Task.ViewMode == v ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;

// Special cases for conditional debug modes
if (v == ViewMode.CustomDepth)
b.Visible = GameSettings.Load<GraphicsSettings>().EnableCustomDepth;
}
}

Expand Down
6 changes: 6 additions & 0 deletions Source/Engine/Core/Config/GraphicsSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class
API_FIELD(Attributes = "EditorOrder(1502), EditorDisplay(\"Quality\")")
bool UseHDRProbes = false;

/// <summary>
/// If checked, enables custom depth rendering. This can be used in materials.
/// </summary>
API_FIELD(Attributes = "EditorOrder(1600), EditorDisplay(\"Custom Depth\")")
bool EnableCustomDepth = false;

/// <summary>
/// If checked, enables Global SDF rendering. This can be used in materials, shaders, and particles.
/// </summary>
Expand Down
13 changes: 12 additions & 1 deletion Source/Engine/Graphics/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,12 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
/// </summary>
GlobalSurfaceAtlas = 1 << 6,

/// <summary>
/// The custom depth rendering pass. Only certain models will be rendered to this depth.
/// </summary>
API_ENUM(Attributes="HideInEditor")
CustomDepth = 1 << 7,

/// <summary>
/// The debug quad overdraw rendering (editor-only).
/// </summary>
Expand All @@ -761,7 +767,7 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
/// The all draw passes combined into a single mask.
/// </summary>
API_ENUM(Attributes="HideInEditor")
All = Depth | GBuffer | Forward | Distortion | MotionVectors | GlobalSDF | GlobalSurfaceAtlas,
All = Depth | GBuffer | Forward | Distortion | MotionVectors | GlobalSDF | GlobalSurfaceAtlas | CustomDepth,
};

DECLARE_ENUM_OPERATORS(DrawPass);
Expand Down Expand Up @@ -905,6 +911,11 @@ API_ENUM() enum class ViewMode
/// Draw Global Illumination debug preview (eg. irradiance probes).
/// </summary>
GlobalIllumination = 26,

/// <summary>
/// Draw Custom Depth
/// </summary>
CustomDepth = 27,
};

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ PACK_STRUCT(struct DeferredMaterialShaderData {

DrawPass DeferredMaterialShader::GetDrawModes() const
{
return DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::MotionVectors | DrawPass::QuadOverdraw;
return DrawPass::Depth | DrawPass::CustomDepth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::MotionVectors | DrawPass::QuadOverdraw;
}

bool DeferredMaterialShader::CanUseLightmap() const
Expand Down Expand Up @@ -231,12 +231,15 @@ bool DeferredMaterialShader::Load()
psDesc.PS = nullptr;
}
_cache.Depth.Init(psDesc);
_cache.CustomDepth.Init(psDesc);
psDesc.VS = instancedDepthPassVS;
_cacheInstanced.Depth.Init(psDesc);
_cacheInstanced.CustomDepth.Init(psDesc);

// Depth Pass with skinning
psDesc.VS = _shader->GetVS("VS_Skinned");
_cache.DepthSkinned.Init(psDesc);
_cache.CustomDepthSkinned.Init(psDesc);

return failed;
}
5 changes: 5 additions & 0 deletions Source/Engine/Graphics/Materials/DeferredMaterialShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class DeferredMaterialShader : public MaterialShader
PipelineStateCache DefaultLightmap;
PipelineStateCache Depth;
PipelineStateCache DepthSkinned;
PipelineStateCache CustomDepth;
PipelineStateCache CustomDepthSkinned;
PipelineStateCache MotionVectors;
PipelineStateCache MotionVectorsSkinned;
PipelineStateCache MotionVectorsSkinnedPerBone;
Expand All @@ -37,6 +39,8 @@ class DeferredMaterialShader : public MaterialShader
return useLightmap ? &DefaultLightmap : (useSkinning ? &DefaultSkinned : &Default);
case DrawPass::MotionVectors:
return useSkinning ? (perBoneMotionBlur ? &MotionVectorsSkinnedPerBone : &MotionVectorsSkinned) : &MotionVectors;
case DrawPass::CustomDepth:
return useSkinning ? &CustomDepthSkinned : &CustomDepth;
#if USE_EDITOR
case DrawPass::QuadOverdraw:
return useSkinning ? &QuadOverdrawSkinned : &QuadOverdraw;
Expand All @@ -53,6 +57,7 @@ class DeferredMaterialShader : public MaterialShader
DefaultLightmap.Release();
Depth.Release();
DepthSkinned.Release();
CustomDepth.Release();
MotionVectors.Release();
MotionVectorsSkinned.Release();
#if USE_EDITOR
Expand Down
5 changes: 5 additions & 0 deletions Source/Engine/Graphics/Materials/MaterialInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ API_ENUM() enum class MaterialSceneTextures
/// The scene world-space position (relative to the render view origin).
/// </summary>
WorldPosition = 11,

/// <summary>
/// The custom depth.
/// </summary>
CustomDepth = 12,
};

/// <summary>
Expand Down
10 changes: 10 additions & 0 deletions Source/Engine/Graphics/Materials/MaterialParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,16 @@ void MaterialParameter::Bind(BindMeta& meta) const
case MaterialSceneTextures::Specular:
view = meta.CanSampleGBuffer ? meta.Buffers->GBuffer2->View() : nullptr;
break;
case MaterialSceneTextures::CustomDepth:
if (meta.Buffers->CustomDepthBuffer->IsAllocated())
view = meta.CanSampleDepth
? EnumHasAnyFlags(meta.Buffers->CustomDepthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView)
? meta.Buffers->CustomDepthBuffer->ViewReadOnlyDepth()
: meta.Buffers->CustomDepthBuffer->View()
: GPUDevice::Instance->GetDefaultWhiteTexture()->View();
else
view = GPUDevice::Instance->GetDefaultWhiteTexture()->View();
break;
default: ;
}
}
Expand Down
8 changes: 8 additions & 0 deletions Source/Engine/Graphics/RenderBuffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ RenderBuffers::RenderBuffers(const SpawnParams& params)
{
#define CREATE_TEXTURE(name) name = GPUDevice::Instance->CreateTexture(TEXT(#name)); _resources.Add(name)
CREATE_TEXTURE(DepthBuffer);
CREATE_TEXTURE(CustomDepthBuffer);
CREATE_TEXTURE(MotionVectors);
CREATE_TEXTURE(GBuffer0);
CREATE_TEXTURE(GBuffer1);
Expand Down Expand Up @@ -161,6 +162,9 @@ bool RenderBuffers::Init(int32 width, int32 height)
desc.Flags |= GPUTextureFlags::ReadOnlyDepthView;
result |= DepthBuffer->Init(desc);

// CustomDepthPass initializes the custom depth buffer as required.
CustomDepthBuffer->ReleaseGPU();

// MotionBlurPass initializes MotionVectors texture if needed (lazy init - not every game needs it)
MotionVectors->ReleaseGPU();

Expand Down Expand Up @@ -214,6 +218,10 @@ void RenderBuffers::Release()
LocalShadowedLightScattering = nullptr;
LastFrameVolumetricFog = 0;

CustomDepthBuffer->ReleaseGPU();
CustomDepthClear = false;
LastFrameCustomDepth = 0;

#define UPDATE_LAZY_KEEP_RT(name) \
RenderTargetPool::Release(name); \
name = nullptr; \
Expand Down
9 changes: 9 additions & 0 deletions Source/Engine/Graphics/RenderBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject
GPUTexture* TemporalAA = nullptr;
uint64 LastFrameTemporalAA = 0;

// Custom Depth State
bool CustomDepthClear = false;
uint64 LastFrameCustomDepth = 0;

// Maps the custom buffer type into the object that holds the state.
Array<CustomBuffer*, HeapAllocation> CustomBuffers;

Expand Down Expand Up @@ -200,6 +204,11 @@ API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject
/// </summary>
API_FIELD(ReadOnly) GPUTexture* DepthBuffer;

/// <summary>
/// Gets the custom depth buffer render target allocated within this render buffers collection (read only).
/// </summary>
API_FIELD(ReadOnly) GPUTexture* CustomDepthBuffer;

/// <summary>
/// Gets the motion vectors render target allocated within this render buffers collection (read only).
/// </summary>
Expand Down
24 changes: 24 additions & 0 deletions Source/Engine/Level/Actors/ModelInstanceActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "ModelInstanceActor.h"
#include "Engine/Content/Assets/MaterialInstance.h"
#include "Engine/Level/Scene/SceneRendering.h"
#include "Engine/Serialization/Serialization.h"

ModelInstanceActor::ModelInstanceActor(const SpawnParams& params)
: Actor(params)
Expand Down Expand Up @@ -48,6 +49,29 @@ MaterialInstance* ModelInstanceActor::CreateAndSetVirtualMaterialInstance(int32
return result;
}

void ModelInstanceActor::SetDrawCustomDepth(bool value)
{
_drawCustomDepth = value;
}

void ModelInstanceActor::Serialize(SerializeStream& stream, const void* otherObj)
{
Actor::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(ModelInstanceActor);

SERIALIZE_MEMBER(DrawCustomDepth, _drawCustomDepth);
}

void ModelInstanceActor::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
Actor::Deserialize(stream, modifier);

DESERIALIZE_MEMBER(DrawCustomDepth, _drawCustomDepth);

// Update state
SetDrawCustomDepth(_drawCustomDepth);
}

void ModelInstanceActor::WaitForModelLoad()
{
}
Expand Down
21 changes: 21 additions & 0 deletions Source/Engine/Level/Actors/ModelInstanceActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,34 @@ API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor
/// </summary>
virtual void UpdateBounds() = 0;

/// <summary>
/// Gets if this model should draw to the custom depth buffer.
/// </summary>
/// <returns>If this model should draw to the custom depth buffer.</returns>
API_PROPERTY(Attributes = "Serialize")
FORCE_INLINE const bool GetDrawCustomDepth() const
{
return _drawCustomDepth;
}

/// <summary>
/// Sets if this model should draw to the custom depth buffer.
/// </summary>
/// <param name="value">If this model should draw to the custom depth buffer.</param>
API_PROPERTY() void SetDrawCustomDepth(bool value);

private:
bool _drawCustomDepth = false;

protected:
virtual void WaitForModelLoad();

public:
// [Actor]
void OnLayerChanged() override;
void OnTransformChanged() override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;

protected:
// [Actor]
Expand Down
4 changes: 2 additions & 2 deletions Source/Engine/Level/Actors/StaticModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ void StaticModel::Draw(RenderContext& renderContext)
draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex);
draw.LightmapUVs = &Lightmap.UVsArea;
draw.Flags = _staticFlags;
draw.DrawModes = DrawModes;
draw.DrawModes = DrawModes | (GetDrawCustomDepth() ? DrawPass::CustomDepth : DrawPass::None);
draw.Bounds = _sphere;
draw.Bounds.Center -= renderContext.View.Origin;
draw.PerInstanceRandom = GetPerInstanceRandom();
Expand Down Expand Up @@ -383,7 +383,7 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex);
draw.LightmapUVs = &Lightmap.UVsArea;
draw.Flags = _staticFlags;
draw.DrawModes = DrawModes;
draw.DrawModes = DrawModes | (GetDrawCustomDepth() ? DrawPass::CustomDepth : DrawPass::None);
draw.Bounds = _sphere;
draw.Bounds.Center -= renderContext.View.Origin;
draw.PerInstanceRandom = GetPerInstanceRandom();
Expand Down
62 changes: 62 additions & 0 deletions Source/Engine/Renderer/CustomDepthPass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "CustomDepthPass.h"
#include "RenderList.h"

#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPUContext.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderTargetPool.h"
#include "Engine/Engine/Engine.h"

String CustomDepthPass::ToString() const
{
return TEXT("CustomDepthPass");
}

void CustomDepthPass::Render(RenderContext& renderContext)
{
PROFILE_GPU_CPU_NAMED("CustomDepth");

auto device = GPUDevice::Instance;
auto context = device->GetMainContext();

if (!renderContext.Buffers->CustomDepthBuffer->IsAllocated())
{
int width = renderContext.Buffers->GetWidth();
int height = renderContext.Buffers->GetHeight();
GPUTextureDescription desc = GPUTextureDescription::New2D(width, height, GPU_DEPTH_BUFFER_PIXEL_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil);
if (GPUDevice::Instance->Limits.HasReadOnlyDepth)
desc.Flags |= GPUTextureFlags::ReadOnlyDepthView;

renderContext.Buffers->CustomDepthBuffer->Init(desc);
}

renderContext.View.Pass = DrawPass::CustomDepth;

context->ClearDepth(*renderContext.Buffers->CustomDepthBuffer);

context->SetRenderTarget(*renderContext.Buffers->CustomDepthBuffer, static_cast<GPUTextureView*>(nullptr));
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::CustomDepth);

context->ResetRenderTarget();
renderContext.Buffers->CustomDepthClear = false;
renderContext.Buffers->LastFrameCustomDepth = Engine::FrameCount;
}

void CustomDepthPass::Clear(RenderContext& renderContext)
{
// Release the buffer after a while
if (Engine::FrameCount - renderContext.Buffers->LastFrameCustomDepth > 240 && renderContext.Buffers->CustomDepthBuffer->IsAllocated())
renderContext.Buffers->CustomDepthBuffer->ReleaseGPU();

// Only clear depth once and only if it's allocated
if (renderContext.Buffers->CustomDepthClear || !renderContext.Buffers->CustomDepthBuffer->IsAllocated())
return;

PROFILE_GPU_CPU_NAMED("CustomDepthClear");

auto device = GPUDevice::Instance;
auto context = device->GetMainContext();
context->ClearDepth(*renderContext.Buffers->CustomDepthBuffer);
renderContext.Buffers->CustomDepthClear = true;
}
18 changes: 18 additions & 0 deletions Source/Engine/Renderer/CustomDepthPass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "Engine/Graphics/RenderView.h"
#include "RendererPass.h"
#include "Engine/Content/Assets/Shader.h"

/// <summary>
/// Custom Depth Pass.
/// </summary>
class CustomDepthPass : public RendererPass<CustomDepthPass>
{
public:
void Render(RenderContext& renderContext);
void Clear(RenderContext& renderContext);
public:
// [RendererPass]
String ToString() const override;
};