diff --git a/Content/Editor/MaterialTemplates/Deformable.shader b/Content/Editor/MaterialTemplates/Deformable.shader
index cd11eb179..6d5d2d753 100644
--- a/Content/Editor/MaterialTemplates/Deformable.shader
+++ b/Content/Editor/MaterialTemplates/Deformable.shader
@@ -384,9 +384,9 @@ void PS_Depth(PixelInput input)
#include "./Flax/Editor/QuadOverdraw.hlsl"
-// Pixel Shader function for Quad Overdraw Pass (editor-only)
+// Pixel Shader function for Quad Overdraw Pass (development-only)
[earlydepthstencil]
-META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
+META_PS(true, FEATURE_LEVEL_SM5)
META_FLAG(DevelopmentOnly)
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
{
diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader
index 0405ebf1a..d3fec2818 100644
--- a/Content/Editor/MaterialTemplates/Particle.shader
+++ b/Content/Editor/MaterialTemplates/Particle.shader
@@ -687,9 +687,9 @@ void PS_Depth(PixelInput input)
#include "./Flax/Editor/QuadOverdraw.hlsl"
-// Pixel Shader function for Quad Overdraw Pass (editor-only)
+// Pixel Shader function for Quad Overdraw Pass (development-only)
[earlydepthstencil]
-META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
+META_PS(true, FEATURE_LEVEL_SM5)
META_FLAG(DevelopmentOnly)
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
{
diff --git a/Content/Editor/MaterialTemplates/Surface.shader b/Content/Editor/MaterialTemplates/Surface.shader
index 7df7bc9e9..da3a4ada7 100644
--- a/Content/Editor/MaterialTemplates/Surface.shader
+++ b/Content/Editor/MaterialTemplates/Surface.shader
@@ -591,9 +591,9 @@ void PS_Depth(PixelInput input)
#include "./Flax/Editor/QuadOverdraw.hlsl"
-// Pixel Shader function for Quad Overdraw Pass (editor-only)
+// Pixel Shader function for Quad Overdraw Pass (development-only)
[earlydepthstencil]
-META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
+META_PS(true, FEATURE_LEVEL_SM5)
META_FLAG(DevelopmentOnly)
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
{
diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader
index 2876bf2b9..ba4fb494f 100644
--- a/Content/Editor/MaterialTemplates/Terrain.shader
+++ b/Content/Editor/MaterialTemplates/Terrain.shader
@@ -468,9 +468,9 @@ void PS_Depth(PixelInput input)
#include "./Flax/Editor/QuadOverdraw.hlsl"
-// Pixel Shader function for Quad Overdraw Pass (editor-only)
+// Pixel Shader function for Quad Overdraw Pass (development-only)
[earlydepthstencil]
-META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
+META_PS(true, FEATURE_LEVEL_SM5)
META_FLAG(DevelopmentOnly)
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
{
diff --git a/Content/Shaders/Quad.flax b/Content/Shaders/Quad.flax
index 3a3422839..47052775c 100644
--- a/Content/Shaders/Quad.flax
+++ b/Content/Shaders/Quad.flax
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:512a5a44a2e04cf0c0029da894cd7d0cf53dc9254da2c5eab4f6b9eff7f60cd8
-size 4087
+oid sha256:315e569f82c405d73ff72fbf53ec5b380d5c207f7fd0f9d715a937806bb72291
+size 4533
diff --git a/Source/Engine/Graphics/Enums.h b/Source/Engine/Graphics/Enums.h
index e875de4b2..639899d9a 100644
--- a/Source/Engine/Graphics/Enums.h
+++ b/Source/Engine/Graphics/Enums.h
@@ -851,11 +851,17 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
GlobalSurfaceAtlas = 1 << 6,
///
- /// The debug quad overdraw rendering (editor-only).
+ /// The debug quad overdraw rendering (development-only).
///
API_ENUM(Attributes="HideInEditor")
QuadOverdraw = 1 << 20,
+ ///
+ /// The debug wireframe rendering (development-only).
+ ///
+ API_ENUM(Attributes="HideInEditor")
+ Wireframe = 1 << 21,
+
///
/// The default set of draw passes for the scene objects.
///
@@ -947,7 +953,7 @@ API_ENUM() enum class ViewMode
Reflections = 13,
///
- /// Draw scene objects in wireframe mode
+ /// Draw scene objects in wireframe mode (development-only)
///
Wireframe = 14,
diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
index 819870cdc..6bcbb23e8 100644
--- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
@@ -17,11 +17,6 @@
#include "Engine/Renderer/Lightmaps.h"
#endif
-DrawPass DeferredMaterialShader::GetDrawModes() const
-{
- return DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::MotionVectors | DrawPass::QuadOverdraw;
-}
-
bool DeferredMaterialShader::CanUseLightmap() const
{
return true;
@@ -73,7 +68,6 @@ void DeferredMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -87,7 +81,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
const auto cache = params.Instanced ? &_cacheInstanced : &_cache;
PipelineStateCache* psCache = cache->GetPS(view.Pass, useLightmap, useSkinning, usePerBoneMotionBlur);
ASSERT(psCache);
- GPUPipelineState* state = psCache->GetPS(this, cullMode, wireframe);
+ GPUPipelineState* state = psCache->GetPS(this, cullMode);
// Bind pipeline
context->SetState(state);
@@ -107,10 +101,12 @@ bool DeferredMaterialShader::Load()
{
// TODO: support instancing when using ForwardShadingFeature
_instanced = _info.BlendMode == MaterialBlendMode::Opaque && _info.ShadingModel != MaterialShadingModel::CustomLit;
-
+ _drawModes = DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::MotionVectors | DrawPass::Wireframe;
bool failed = false;
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.CullMode = _info.CullMode;
if (EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest))
{
psDesc.DepthFunc = ComparisonFunc::Always;
@@ -136,23 +132,23 @@ bool DeferredMaterialShader::Load()
auto vsInstanced = _shader->GetVS("VS", 1);
auto vsSkinned = _shader->GetVS("VS_Skinned");
auto vsSkinnedInstanced = _shader->GetVS("VS_Skinned", 2);
+ failed |= vs == nullptr;
+ failed |= vsInstanced == nullptr;
+ failed |= vsSkinned == nullptr;
+ failed |= vsSkinnedInstanced == nullptr;
// GBuffer Pass
psDesc.VS = vs;
- failed |= psDesc.VS == nullptr;
psDesc.PS = _shader->GetPS("PS_GBuffer");
_cache.Default.Init(psDesc);
psDesc.VS = vsInstanced;
- failed |= psDesc.VS == nullptr;
_cacheInstanced.Default.Init(psDesc);
// GBuffer Pass with lightmap (USE_LIGHTMAP=1)
psDesc.VS = vs;
- failed |= psDesc.VS == nullptr;
psDesc.PS = _shader->GetPS("PS_GBuffer", 1);
_cache.DefaultLightmap.Init(psDesc);
psDesc.VS = vsInstanced;
- failed |= psDesc.VS == nullptr;
_cacheInstanced.DefaultLightmap.Init(psDesc);
// GBuffer Pass with skinning (USE_SKINNING=1)
@@ -169,16 +165,34 @@ bool DeferredMaterialShader::Load()
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
+ _drawModes |= DrawPass::QuadOverdraw;
psDesc.VS = vs;
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
_cache.QuadOverdraw.Init(psDesc);
psDesc.VS = vsInstanced;
- _cacheInstanced.Depth.Init(psDesc);
+ _cacheInstanced.QuadOverdraw.Init(psDesc);
psDesc.VS = vsSkinned;
_cache.QuadOverdrawSkinned.Init(psDesc);
psDesc.VS = vsSkinnedInstanced;
_cacheInstanced.QuadOverdrawSkinned.Init(psDesc);
}
+
+ // Wireframe
+ psDesc.Wireframe = true;
+ psDesc.DepthWriteEnable = false;
+ psDesc.BlendMode = BlendingMode::AlphaBlend;
+ psDesc.PS = GPUDevice::Instance->QuadShader->GetPS("PS_Wireframe");
+ psDesc.VS = vs;
+ _cache.Wireframe.Init(psDesc);
+ psDesc.VS = vsInstanced;
+ _cacheInstanced.Wireframe.Init(psDesc);
+ psDesc.VS = vsSkinned;
+ _cache.WireframeSkinned.Init(psDesc);
+ psDesc.VS = vsSkinnedInstanced;
+ _cacheInstanced.WireframeSkinned.Init(psDesc);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.BlendMode = BlendingMode::Opaque;
#endif
// Motion Vectors pass
diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.h b/Source/Engine/Graphics/Materials/DeferredMaterialShader.h
index 182fc1939..9ce82572d 100644
--- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.h
+++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.h
@@ -23,6 +23,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
PipelineStateCache QuadOverdrawSkinned;
+ PipelineStateCache Wireframe;
+ PipelineStateCache WireframeSkinned;
#endif
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap, const bool useSkinning, const bool perBoneMotionBlur)
@@ -40,6 +42,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return useSkinning ? &QuadOverdrawSkinned : &QuadOverdraw;
+ case DrawPass::Wireframe:
+ return useSkinning ? &WireframeSkinned : &Wireframe;
#endif
default:
return nullptr;
@@ -58,6 +62,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
QuadOverdrawSkinned.Release();
+ Wireframe.Release();
+ WireframeSkinned.Release();
#endif
}
};
@@ -75,7 +81,6 @@ public:
public:
// [MaterialShader]
- DrawPass GetDrawModes() const override;
bool CanUseLightmap() const override;
bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const override;
void Bind(BindParameters& params) override;
diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
index 5a2323aac..6cf7865d7 100644
--- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
@@ -82,7 +82,6 @@ void DeformableMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant)
{
@@ -91,7 +90,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
}
PipelineStateCache* psCache = _cache.GetPS(view.Pass);
ASSERT(psCache);
- GPUPipelineState* state = psCache->GetPS(this, cullMode, wireframe);
+ GPUPipelineState* state = psCache->GetPS(this, cullMode);
// Bind pipeline
context->SetState(state);
@@ -108,10 +107,12 @@ void DeformableMaterialShader::Unload()
bool DeformableMaterialShader::Load()
{
- _drawModes = DrawPass::Depth | DrawPass::QuadOverdraw;
+ _drawModes = DrawPass::Depth | DrawPass::QuadOverdraw | DrawPass::Wireframe;
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
+ psDesc.DepthEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.CullMode = _info.CullMode;
psDesc.VS = _shader->GetVS("VS_SplineModel");
#if GPU_ALLOW_TESSELLATION_SHADERS
@@ -128,9 +129,20 @@ bool DeformableMaterialShader::Load()
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
+ _drawModes |= DrawPass::QuadOverdraw;
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
_cache.QuadOverdraw.Init(psDesc);
}
+
+ // Wireframe
+ psDesc.Wireframe = true;
+ psDesc.DepthWriteEnable = false;
+ psDesc.BlendMode = BlendingMode::AlphaBlend;
+ psDesc.PS = GPUDevice::Instance->QuadShader->GetPS("PS_Wireframe");
+ _cache.Wireframe.Init(psDesc);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.BlendMode = BlendingMode::Opaque;
#endif
if (_info.BlendMode == MaterialBlendMode::Opaque)
diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.h b/Source/Engine/Graphics/Materials/DeformableMaterialShader.h
index 90b3ef4af..ba33ee8f8 100644
--- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.h
+++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.h
@@ -17,6 +17,7 @@ private:
PipelineStateCache Distortion;
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
+ PipelineStateCache Wireframe;
#endif
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
@@ -35,6 +36,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return &QuadOverdraw;
+ case DrawPass::Wireframe:
+ return &Wireframe;
#endif
default:
return nullptr;
@@ -48,13 +51,13 @@ private:
Distortion.Release();
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
+ Wireframe.Release();
#endif
}
};
private:
Cache _cache;
- DrawPass _drawModes = DrawPass::None;
public:
DeformableMaterialShader(const StringView& name)
diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
index eb0f63f1a..676c765ab 100644
--- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
@@ -72,7 +72,6 @@ void ForwardMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -87,7 +86,7 @@ void ForwardMaterialShader::Bind(BindParameters& params)
const auto cacheObj = params.Instanced ? &_cacheInstanced : &_cache;
PipelineStateCache* psCache = cacheObj->GetPS(view.Pass, useSkinning);
ASSERT(psCache);
- GPUPipelineState* state = psCache->GetPS(this, cullMode, wireframe);
+ GPUPipelineState* state = psCache->GetPS(this, cullMode);
// Bind pipeline
context->SetState(state);
@@ -104,11 +103,12 @@ void ForwardMaterialShader::Unload()
bool ForwardMaterialShader::Load()
{
- _drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
-
+ _drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw | DrawPass::Wireframe;
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
+ psDesc.DepthEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.CullMode = _info.CullMode;
#if GPU_ALLOW_TESSELLATION_SHADERS
// Check if use tessellation (both material and runtime supports it)
@@ -124,14 +124,29 @@ bool ForwardMaterialShader::Load()
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
+ _drawModes |= DrawPass::QuadOverdraw;
psDesc.VS = _shader->GetVS("VS");
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
_cache.QuadOverdraw.Init(psDesc);
psDesc.VS = _shader->GetVS("VS", 1);
- _cacheInstanced.Depth.Init(psDesc);
+ _cacheInstanced.QuadOverdraw.Init(psDesc);
psDesc.VS = _shader->GetVS("VS_Skinned");
_cache.QuadOverdrawSkinned.Init(psDesc);
}
+
+ // Wireframe
+ psDesc.Wireframe = true;
+ psDesc.DepthWriteEnable = false;
+ psDesc.BlendMode = BlendingMode::AlphaBlend;
+ psDesc.PS = GPUDevice::Instance->QuadShader->GetPS("PS_Wireframe");
+ psDesc.VS = _shader->GetVS("VS");
+ _cache.Wireframe.Init(psDesc);
+ psDesc.VS = _shader->GetVS("VS", 1);
+ _cacheInstanced.Wireframe.Init(psDesc);
+ psDesc.VS = _shader->GetVS("VS_Skinned");
+ _cache.WireframeSkinned.Init(psDesc);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
#endif
// Check if use transparent distortion pass
diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.h b/Source/Engine/Graphics/Materials/ForwardMaterialShader.h
index 15e49e1af..f40bc10f6 100644
--- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.h
+++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.h
@@ -21,6 +21,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
PipelineStateCache QuadOverdrawSkinned;
+ PipelineStateCache Wireframe;
+ PipelineStateCache WireframeSkinned;
#endif
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useSkinning)
@@ -36,6 +38,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return useSkinning ? &QuadOverdrawSkinned : &QuadOverdraw;
+ case DrawPass::Wireframe:
+ return useSkinning ? &WireframeSkinned : &Wireframe;
#endif
default:
return nullptr;
@@ -53,6 +57,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
QuadOverdrawSkinned.Release();
+ Wireframe.Release();
+ WireframeSkinned.Release();
#endif
}
};
@@ -60,7 +66,6 @@ private:
private:
Cache _cache;
Cache _cacheInstanced;
- DrawPass _drawModes = DrawPass::None;
public:
///
diff --git a/Source/Engine/Graphics/Materials/MaterialShader.cpp b/Source/Engine/Graphics/Materials/MaterialShader.cpp
index c1faa53da..e07c289d4 100644
--- a/Source/Engine/Graphics/Materials/MaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/MaterialShader.cpp
@@ -118,10 +118,9 @@ void IMaterial::BindParameters::BindDrawData()
GPUContext->BindCB(2, PerDrawConstants);
}
-GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(const MaterialShader* owner, CullMode mode, bool wireframe)
+GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(const MaterialShader* owner, CullMode mode)
{
Desc.CullMode = mode;
- Desc.Wireframe = wireframe;
auto ps = GPUDevice::Instance->CreatePipelineState();
if (ps->Init(Desc))
{
@@ -231,6 +230,11 @@ GPUShader* MaterialShader::GetShader() const
return _shader;
}
+DrawPass MaterialShader::GetDrawModes() const
+{
+ return _drawModes;
+}
+
const MaterialInfo& MaterialShader::GetInfo() const
{
return _info;
@@ -248,6 +252,7 @@ bool MaterialShader::Load(MemoryReadStream& shaderCacheStream, const MaterialInf
// Cache material info
_info = info;
+ _drawModes = DrawPass::None;
// Create shader
if (_shader->Create(shaderCacheStream))
diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h
index fa3d47629..e114baff8 100644
--- a/Source/Engine/Graphics/Materials/MaterialShader.h
+++ b/Source/Engine/Graphics/Materials/MaterialShader.h
@@ -31,7 +31,7 @@ class MaterialShader : public IMaterial
protected:
struct PipelineStateCache
{
- GPUPipelineState* PS[6];
+ GPUPipelineState* PS[3];
GPUPipelineState::Description Desc;
PipelineStateCache()
@@ -44,16 +44,16 @@ protected:
Desc = desc;
}
- GPUPipelineState* GetPS(const MaterialShader* owner, CullMode mode, bool wireframe)
+ GPUPipelineState* GetPS(const MaterialShader* owner, CullMode mode)
{
- const int32 index = static_cast(mode) + (wireframe ? 3 : 0);
+ const int32 index = (int32)mode;
auto ps = PS[index];
if (!ps)
- PS[index] = ps = InitPS(owner, mode, wireframe);
+ PS[index] = ps = InitPS(owner, mode);
return ps;
}
- GPUPipelineState* InitPS(const MaterialShader* owner, CullMode mode, bool wireframe);
+ GPUPipelineState* InitPS(const MaterialShader* owner, CullMode mode);
void Release()
{
@@ -63,6 +63,7 @@ protected:
protected:
bool _isLoaded;
+ DrawPass _drawModes = DrawPass::None;
GPUShader* _shader;
GPUConstantBuffer* _cb;
Array _cbData;
@@ -110,6 +111,7 @@ protected:
public:
// [IMaterial]
+ DrawPass GetDrawModes() const override;
const MaterialInfo& GetInfo() const override;
GPUShader* GetShader() const override;
bool IsReady() const override;
diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
index 0c2b1861d..be983f148 100644
--- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
@@ -38,11 +38,6 @@ PACK_STRUCT(struct ParticleMaterialShaderData {
Matrix3x4 WorldMatrixInverseTransposed;
});
-DrawPass ParticleMaterialShader::GetDrawModes() const
-{
- return _drawModes;
-}
-
void ParticleMaterialShader::Bind(BindParameters& params)
{
// Prepare
@@ -119,7 +114,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- bool wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe) || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
PipelineStateCache* psCache = nullptr;
switch (drawCall.Particle.Module->TypeID)
@@ -160,7 +154,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
}
}
ASSERT(psCache);
- GPUPipelineState* state = psCache->GetPS(this, cullMode, wireframe);
+ GPUPipelineState* state = psCache->GetPS(this, cullMode);
// Bind constants
if (_cb)
@@ -186,44 +180,52 @@ void ParticleMaterialShader::Unload()
bool ParticleMaterialShader::Load()
{
- _drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
- GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
+ _drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::Wireframe;
+ auto psDesc = GPUPipelineState::Description::Default;
+ psDesc.DepthEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.CullMode = _info.CullMode;
auto vsSprite = _shader->GetVS("VS_Sprite");
auto vsMesh = _shader->GetVS("VS_Model");
auto vsRibbon = _shader->GetVS("VS_Ribbon");
+#define INIT_CACHE(type) \
+ psDesc.VS = vsSprite; \
+ _cacheSprite.type.Init(psDesc); \
+ psDesc.VS = vsMesh; \
+ _cacheModel.type.Init(psDesc); \
+ psDesc.VS = vsRibbon; \
+ _cacheRibbon.type.Init(psDesc)
#if GPU_ENABLE_DEVELOPMENT
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
+ _drawModes |= DrawPass::QuadOverdraw;
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
- psDesc.VS = vsSprite;
- _cacheSprite.QuadOverdraw.Init(psDesc);
- psDesc.VS = vsMesh;
- _cacheModel.QuadOverdraw.Init(psDesc);
- psDesc.VS = vsRibbon;
- _cacheRibbon.QuadOverdraw.Init(psDesc);
+ INIT_CACHE(QuadOverdraw);
}
+
+ // Wireframe
+ psDesc.Wireframe = true;
+ psDesc.DepthWriteEnable = false;
+ psDesc.BlendMode = BlendingMode::AlphaBlend;
+ psDesc.PS = GPUDevice::Instance->QuadShader->GetPS("PS_Wireframe");
+ INIT_CACHE(Wireframe);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
#endif
// Check if use transparent distortion pass
if (_shader->HasShader("PS_Distortion"))
{
- _drawModes |= DrawPass::Distortion;
-
// Accumulate Distortion Pass
+ _drawModes |= DrawPass::Distortion;
psDesc.PS = _shader->GetPS("PS_Distortion");
psDesc.BlendMode = BlendingMode::Add;
psDesc.DepthWriteEnable = false;
- psDesc.VS = vsSprite;
- _cacheSprite.Distortion.Init(psDesc);
- psDesc.VS = vsMesh;
- _cacheModel.Distortion.Init(psDesc);
- psDesc.VS = vsRibbon;
- _cacheRibbon.Distortion.Init(psDesc);
+ INIT_CACHE(Distortion);
}
// Forward Pass
@@ -242,12 +244,7 @@ bool ParticleMaterialShader::Load()
psDesc.BlendMode = BlendingMode::Multiply;
break;
}
- psDesc.VS = vsSprite;
- _cacheSprite.Default.Init(psDesc);
- psDesc.VS = vsMesh;
- _cacheModel.Default.Init(psDesc);
- psDesc.VS = vsRibbon;
- _cacheRibbon.Default.Init(psDesc);
+ INIT_CACHE(Default);
// Depth Pass
psDesc = GPUPipelineState::Description::Default;
@@ -255,12 +252,7 @@ bool ParticleMaterialShader::Load()
psDesc.DepthClipEnable = false;
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None;
psDesc.PS = _shader->GetPS("PS_Depth");
- psDesc.VS = vsSprite;
- _cacheSprite.Depth.Init(psDesc);
- psDesc.VS = vsMesh;
- _cacheModel.Depth.Init(psDesc);
- psDesc.VS = vsRibbon;
- _cacheRibbon.Depth.Init(psDesc);
+ INIT_CACHE(Depth);
// Lazy initialization
_cacheVolumetricFog.Desc.PS = nullptr;
diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.h b/Source/Engine/Graphics/Materials/ParticleMaterialShader.h
index ab0e6efc9..01b4389b6 100644
--- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.h
+++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.h
@@ -17,6 +17,7 @@ private:
PipelineStateCache Distortion;
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
+ PipelineStateCache Wireframe;
#endif
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
@@ -32,6 +33,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return &QuadOverdraw;
+ case DrawPass::Wireframe:
+ return &Wireframe;
#endif
default:
return nullptr;
@@ -45,6 +48,7 @@ private:
Distortion.Release();
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
+ Wireframe.Release();
#endif
}
};
@@ -54,7 +58,6 @@ private:
Cache _cacheModel;
Cache _cacheRibbon;
PipelineStateCache _cacheVolumetricFog;
- DrawPass _drawModes = DrawPass::None;
public:
///
@@ -68,7 +71,6 @@ public:
public:
// [MaterialShader]
- DrawPass GetDrawModes() const override;
void Bind(BindParameters& params) override;
void Unload() override;
diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
index 25590d9ca..19942f6a1 100644
--- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
@@ -30,11 +30,6 @@ PACK_STRUCT(struct TerrainMaterialShaderData {
Float4 LightmapArea;
});
-DrawPass TerrainMaterialShader::GetDrawModes() const
-{
- return DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas;
-}
-
bool TerrainMaterialShader::CanUseLightmap() const
{
return true;
@@ -101,7 +96,6 @@ void TerrainMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe) || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -112,9 +106,10 @@ void TerrainMaterialShader::Bind(BindParameters& params)
// Invert culling when scale is negative
cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal;
}
+ auto hass = _shader->HasShader("PS_QuadOverdraw");
const PipelineStateCache* psCache = _cache.GetPS(view.Pass, useLightmap);
ASSERT(psCache);
- GPUPipelineState* state = ((PipelineStateCache*)psCache)->GetPS(this, cullMode, wireframe);
+ GPUPipelineState* state = ((PipelineStateCache*)psCache)->GetPS(this, cullMode);
// Bind pipeline
context->SetState(state);
@@ -131,9 +126,12 @@ void TerrainMaterialShader::Unload()
bool TerrainMaterialShader::Load()
{
- GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
+ _drawModes = DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::Wireframe;
+ auto psDesc = GPUPipelineState::Description::Default;
+ psDesc.DepthEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.CullMode = _info.CullMode;
psDesc.StencilEnable = true;
psDesc.StencilReadMask = 0;
@@ -177,9 +175,20 @@ bool TerrainMaterialShader::Load()
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
+ _drawModes |= DrawPass::QuadOverdraw;
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
_cache.QuadOverdraw.Init(psDesc);
}
+
+ // Wireframe
+ psDesc.Wireframe = true;
+ psDesc.DepthWriteEnable = false;
+ psDesc.BlendMode = BlendingMode::AlphaBlend;
+ psDesc.PS = GPUDevice::Instance->QuadShader->GetPS("PS_Wireframe");
+ _cache.Wireframe.Init(psDesc);
+ psDesc.DepthWriteEnable = EnumHasNoneFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthWrite);
+ psDesc.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
+ psDesc.BlendMode = BlendingMode::Opaque;
#endif
// Depth Pass
diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.h b/Source/Engine/Graphics/Materials/TerrainMaterialShader.h
index 9348bcf06..69203a983 100644
--- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.h
+++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.h
@@ -17,6 +17,7 @@ private:
PipelineStateCache Depth;
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
+ PipelineStateCache Wireframe;
#endif
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap)
@@ -32,6 +33,8 @@ private:
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return &QuadOverdraw;
+ case DrawPass::Wireframe:
+ return &Wireframe;
#endif
default:
return nullptr;
@@ -45,6 +48,7 @@ private:
Depth.Release();
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
+ Wireframe.Release();
#endif
}
};
@@ -64,7 +68,6 @@ public:
public:
// [MaterialShader]
- DrawPass GetDrawModes() const override;
bool CanUseLightmap() const override;
void Bind(BindParameters& params) override;
void Unload() override;
diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp
index e8f3bcb6a..fce1d09d3 100644
--- a/Source/Engine/Renderer/Renderer.cpp
+++ b/Source/Engine/Renderer/Renderer.cpp
@@ -403,6 +403,12 @@ PRAGMA_ENABLE_DEPRECATION_WARNINGS
case ViewMode::LightOverlap:
setup.UseShadows = false;
break;
+#if GPU_ENABLE_DEVELOPMENT
+ case ViewMode::Wireframe:
+ // Use FXAA in wireframe view to improve readability (compared to TAA)
+ renderContext.List->Settings.AntiAliasing.Mode = AntialiasingMode::FastApproximateAntialiasing;
+ break;
+#endif
}
if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut || isGBufferDebug || renderContext.View.Mode == ViewMode::NoPostFx)
setup.UseMotionVectors = false;
@@ -451,7 +457,6 @@ PRAGMA_ENABLE_DEPRECATION_WARNINGS
case ViewMode::GlobalSurfaceAtlas:
case ViewMode::LightmapUVsDensity:
case ViewMode::MaterialComplexity:
- case ViewMode::Wireframe:
case ViewMode::NoPostFx:
case ViewMode::VertexColors:
case ViewMode::QuadOverdraw:
@@ -749,15 +754,46 @@ void RenderInner(RenderContext& renderContext, RenderContextBatch& renderContext
renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterForwardPass, frameBuffer, lightBuffer);
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::AfterForwardPass, frameBuffer, lightBuffer);
+#if GPU_ENABLE_DEVELOPMENT
+ // Debug drawing
+ if (renderContext.View.Mode == ViewMode::Wireframe)
+ {
+ // Compose wireframe on top of the scene
+ PROFILE_GPU_CPU_NAMED("Wireframe");
+ renderContext.View.Pass = DrawPass::Wireframe;
+ auto depthBuffer = renderContext.Buffers->GetReadOnlyDepthBuffer();
+ auto cb = GPUDevice::Instance->QuadShader->GetCB(3);
+ GPU_CB_STRUCT(WireframeData {
+ Float4 ColorNear;
+ Float4 ColorFar;
+ });
+ WireframeData data;
+ context->BindCB(3, cb);
+ context->SetRenderTarget(nullptr, *frameBuffer); // 1st pass without depth buffer
+ data.ColorNear = Float4(0.07f, 0.15f, 0.07f, 0.2f);
+ data.ColorFar = Float4(0.06f, 0.06f, 0.1f, 0.05f);
+ context->UpdateCB(cb, &data);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBufferNoDecals);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Forward);
+ context->SetRenderTarget(depthBuffer.RTV, *frameBuffer); // 2nd pass with depth buffer (read-only)
+ data.ColorNear = Float4(0.2f, 0.1f, 0.15f, 1.0);
+ data.ColorFar = Float4(0.1f, 0.15f, 0.4f, 0.7f);
+ context->UpdateCB(cb, &data);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBufferNoDecals);
+ renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Forward);
+ }
+#endif
+
// Cleanup
context->ResetRenderTarget();
context->ResetSR();
context->FlushState();
RenderTargetPool::Release(lightBuffer);
-
- // Check if skip post-processing
- if (renderContext.View.Mode == ViewMode::NoPostFx || renderContext.View.Mode == ViewMode::Wireframe)
+ if (renderContext.View.Mode == ViewMode::NoPostFx)
{
+ // Skip post-processing
context->SetRenderTarget(renderContext.Task->GetOutputView());
context->SetViewportAndScissors(renderContext.Task->GetOutputViewport());
if (!Graphics::GammaColorSpace)
diff --git a/Source/Shaders/Quad.shader b/Source/Shaders/Quad.shader
index 0b318c863..e93e6b8f8 100644
--- a/Source/Shaders/Quad.shader
+++ b/Source/Shaders/Quad.shader
@@ -134,3 +134,22 @@ float4 PS_DecodeNV12(Quad_VS2PS input) : SV_Target
}
#endif
+
+#ifdef _PS_Wireframe
+
+META_CB_BEGIN(3, WireframeData)
+float4 ColorNear;
+float4 ColorFar;
+META_CB_END
+
+// Pixel Shader function for wireframe debug view
+META_PS(true, FEATURE_LEVEL_ES2)
+META_FLAG(DevelopmentOnly)
+float4 PS_Wireframe(float4 SvPosition : SV_Position) : SV_Target0
+{
+ // Depth-based gradient
+ float alpha = saturate(SvPosition.w * UNITS_TO_METERS_SCALE * 0.1f);
+ return lerp(ColorNear, ColorFar, alpha);
+}
+
+#endif