Refactor Wireframe view mode to draw wireframe on top of lit view

This commit is contained in:
2026-08-18 12:01:03 +02:00
parent c83cec1e4e
commit 58edc4c897
20 changed files with 230 additions and 102 deletions
@@ -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)
{
@@ -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)
{
@@ -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)
{
@@ -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)
{
Binary file not shown.
+8 -2
View File
@@ -851,11 +851,17 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
GlobalSurfaceAtlas = 1 << 6,
/// <summary>
/// The debug quad overdraw rendering (editor-only).
/// The debug quad overdraw rendering (development-only).
/// </summary>
API_ENUM(Attributes="HideInEditor")
QuadOverdraw = 1 << 20,
/// <summary>
/// The debug wireframe rendering (development-only).
/// </summary>
API_ENUM(Attributes="HideInEditor")
Wireframe = 1 << 21,
/// <summary>
/// The default set of draw passes for the scene objects.
/// </summary>
@@ -947,7 +953,7 @@ API_ENUM() enum class ViewMode
Reflections = 13,
/// <summary>
/// Draw scene objects in wireframe mode
/// Draw scene objects in wireframe mode (development-only)
/// </summary>
Wireframe = 14,
@@ -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
@@ -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;
@@ -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)
@@ -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)
@@ -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
@@ -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:
/// <summary>
@@ -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))
@@ -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<int32>(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<byte> _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;
@@ -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;
@@ -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:
/// <summary>
@@ -68,7 +71,6 @@ public:
public:
// [MaterialShader]
DrawPass GetDrawModes() const override;
void Bind(BindParameters& params) override;
void Unload() override;
@@ -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
@@ -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;
+40 -4
View File
@@ -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)
+19
View File
@@ -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