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