diff --git a/CMakeLists.txt b/CMakeLists.txt index 03e54497..865063d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ target_sources(DiligentFX PRIVATE # A target created in the same directory (CMakeLists.txt file) that specifies any output of the # custom command as a source file is given a rule to generate the file using the command at build time. ${SHADERS_INC_LIST} + ${SHADERS_LIST_FILE} ) source_group("generated" FILES ${SHADERS_LIST_FILE} diff --git a/Hydrogent/include/HnRendererImpl.hpp b/Hydrogent/include/HnRendererImpl.hpp index 5114c5c4..8890ee8d 100644 --- a/Hydrogent/include/HnRendererImpl.hpp +++ b/Hydrogent/include/HnRendererImpl.hpp @@ -93,6 +93,7 @@ class HnRendererImpl final : public ObjectBase void PrepareRenderTargets(ITextureView* pDstRtv); void PreparePostProcess(TEXTURE_FORMAT RTVFmt); + void PerformPostProcess(IDeviceContext* pCtx, const HnDrawAttribs& Attribs); private: RenderDeviceWithCache_N m_Device; @@ -100,6 +101,7 @@ class HnRendererImpl final : public ObjectBase RefCntAutoPtr m_CameraAttribsCB; RefCntAutoPtr m_LightAttribsCB; + RefCntAutoPtr m_PostProcessAttribsCB; const bool m_ConvertOutputToSRGB; diff --git a/Hydrogent/interface/HnRenderer.hpp b/Hydrogent/interface/HnRenderer.hpp index 504feffa..cd616eb7 100644 --- a/Hydrogent/interface/HnRenderer.hpp +++ b/Hydrogent/interface/HnRenderer.hpp @@ -86,7 +86,7 @@ struct HnDrawAttribs bool EnablePrimIdQueries = false; float4 WireframeColor = float4{1, 1, 1, 1}; - float4 SlectionColor = float4{0.25f, 0.25f, 0.1f, 0.5f}; + float4 SlectionColor = float4{0.75f, 0.75f, 0.25f, 0.5f}; HN_RENDER_MODE RenderMode = HN_RENDER_MODE_SOLID; diff --git a/Hydrogent/shaders/PostProcess.psh b/Hydrogent/shaders/HnPostProcess.psh similarity index 53% rename from Hydrogent/shaders/PostProcess.psh rename to Hydrogent/shaders/HnPostProcess.psh index a395780f..605aedd2 100644 --- a/Hydrogent/shaders/PostProcess.psh +++ b/Hydrogent/shaders/HnPostProcess.psh @@ -1,8 +1,15 @@ +#include "HnPostProcessStructures.fxh" + struct PSInput { float4 Pos : SV_POSITION; }; +cbuffer cbPostProcessAttribs +{ + PostProcessAttribs g_Attribs; +} + Texture2D g_ColorBuffer; Texture2D g_MeshId; @@ -11,22 +18,27 @@ void main(in PSInput PSIn, { Color = g_ColorBuffer.Load(int3(PSIn.Pos.xy, 0)); - float IsSelected0 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected1 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected2 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0; + float IsSelected0 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected1 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected2 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0; - float IsSelected3 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected4 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected5 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0; + float IsSelected3 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected4 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected5 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0; - float IsSelected6 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected7 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0; - float IsSelected8 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0; + float IsSelected6 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected7 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0; + float IsSelected8 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0; float Outline = IsSelected0 + IsSelected1 + IsSelected2 + IsSelected3 + IsSelected4 + IsSelected5 + IsSelected6 + IsSelected7 + IsSelected8; - Outline = saturate(1.0 - abs(Outline) / 9.0); + //Outline = (9.0 - Outline) * (Outline > 0.0 ? 1.0 / 8.0 : 0.0); + Outline = (Outline > 0.0 && Outline < 9.0) ? 1.0 : 0.0; + + float DesatFactor = g_Attribs.NonselectionDesaturationFactor * saturate(IsSelected4); + float Luminance = dot(Color.rgb, float3(0.2126, 0.7152, 0.0722)); + Color.rgb = lerp(Color.rgb, float3(Luminance, Luminance, Luminance), DesatFactor); - Color.rgb += Outline * float3(0.25, 0.25, 0.1f); + Color.rgb = lerp(Color.rgb, g_Attribs.SelectionOutlineColor.rgb, Outline); #if CONVERT_OUTPUT_TO_SRGB Color.rgb = pow(Color.rgb, float3(1.0/2.2, 1.0/2.2, 1.0/2.2)); diff --git a/Hydrogent/shaders/PostProcess.vsh b/Hydrogent/shaders/HnPostProcess.vsh similarity index 100% rename from Hydrogent/shaders/PostProcess.vsh rename to Hydrogent/shaders/HnPostProcess.vsh diff --git a/Hydrogent/shaders/HnPostProcessStructures.fxh b/Hydrogent/shaders/HnPostProcessStructures.fxh new file mode 100644 index 00000000..bbc30427 --- /dev/null +++ b/Hydrogent/shaders/HnPostProcessStructures.fxh @@ -0,0 +1,14 @@ +#ifndef _HN_POST_PROCESS_STRUCTURES_FXH_ +#define _HN_POST_PROCESS_STRUCTURES_FXH_ + +struct PostProcessAttribs +{ + float4 SelectionOutlineColor; + + float NonselectionDesaturationFactor; + float Padding0; + float Padding1; + float Padding2; +}; + +#endif // _HN_POST_PROCESS_STRUCTURES_FXH_ diff --git a/Hydrogent/shaders_inc/HnPostProcess.psh.h b/Hydrogent/shaders_inc/HnPostProcess.psh.h new file mode 100644 index 00000000..97d83db7 --- /dev/null +++ b/Hydrogent/shaders_inc/HnPostProcess.psh.h @@ -0,0 +1,46 @@ +"#include \"HnPostProcessStructures.fxh\"\n" +"\n" +"struct PSInput\n" +"{\n" +" float4 Pos : SV_POSITION;\n" +"};\n" +"\n" +"cbuffer cbPostProcessAttribs\n" +"{\n" +" PostProcessAttribs g_Attribs;\n" +"}\n" +"\n" +"Texture2D g_ColorBuffer;\n" +"Texture2D g_MeshId;\n" +"\n" +"void main(in PSInput PSIn,\n" +" out float4 Color : SV_Target0)\n" +"{\n" +" Color = g_ColorBuffer.Load(int3(PSIn.Pos.xy, 0));\n" +"\n" +" float IsSelected0 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected1 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected2 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +"\n" +" float IsSelected3 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected4 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected5 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +"\n" +" float IsSelected6 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected7 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected8 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +"\n" +" float Outline = IsSelected0 + IsSelected1 + IsSelected2 + IsSelected3 + IsSelected4 + IsSelected5 + IsSelected6 + IsSelected7 + IsSelected8;\n" +" //Outline = (9.0 - Outline) * (Outline > 0.0 ? 1.0 / 8.0 : 0.0);\n" +" Outline = (Outline > 0.0 && Outline < 9.0) ? 1.0 : 0.0;\n" +"\n" +" float DesatFactor = g_Attribs.NonselectionDesaturationFactor * saturate(IsSelected4);\n" +" float Luminance = dot(Color.rgb, float3(0.2126, 0.7152, 0.0722));\n" +" Color.rgb = lerp(Color.rgb, float3(Luminance, Luminance, Luminance), DesatFactor);\n" +"\n" +" Color.rgb = lerp(Color.rgb, g_Attribs.SelectionOutlineColor.rgb, Outline);\n" +"\n" +"#if CONVERT_OUTPUT_TO_SRGB\n" +" Color.rgb = pow(Color.rgb, float3(1.0/2.2, 1.0/2.2, 1.0/2.2));\n" +"#endif\n" +"}\n" diff --git a/Hydrogent/shaders_inc/HnPostProcess.vsh.h b/Hydrogent/shaders_inc/HnPostProcess.vsh.h new file mode 100644 index 00000000..8811f22e --- /dev/null +++ b/Hydrogent/shaders_inc/HnPostProcess.vsh.h @@ -0,0 +1,14 @@ +"struct PSInput\n" +"{\n" +" float4 Pos : SV_POSITION;\n" +"};\n" +"void main(in uint VertID : SV_VertexID,\n" +" out PSInput PSIn)\n" +"{\n" +" float2 ClipXY[3];\n" +" ClipXY[0] = float2(-1.0, -1.0);\n" +" ClipXY[1] = float2(-1.0, 3.0);\n" +" ClipXY[2] = float2( 3.0, -1.0);\n" +"\n" +" PSIn.Pos = float4(ClipXY[VertID], 0.0, 1.0);\n" +"}\n" diff --git a/Hydrogent/shaders_inc/HnPostProcessStructures.fxh.h b/Hydrogent/shaders_inc/HnPostProcessStructures.fxh.h new file mode 100644 index 00000000..1a2639e9 --- /dev/null +++ b/Hydrogent/shaders_inc/HnPostProcessStructures.fxh.h @@ -0,0 +1,14 @@ +"#ifndef _HN_POST_PROCESS_STRUCTURES_FXH_\n" +"#define _HN_POST_PROCESS_STRUCTURES_FXH_\n" +"\n" +"struct PostProcessAttribs\n" +"{\n" +" float4 SelectionOutlineColor;\n" +"\n" +" float NonselectionDesaturationFactor;\n" +" float Padding0;\n" +" float Padding1;\n" +" float Padding2;\n" +"};\n" +"\n" +"#endif // _HN_POST_PROCESS_STRUCTURES_FXH_\n" diff --git a/Hydrogent/shaders_inc/PostProcess.psh.h b/Hydrogent/shaders_inc/PostProcess.psh.h index b64439a6..5efcdc5a 100644 --- a/Hydrogent/shaders_inc/PostProcess.psh.h +++ b/Hydrogent/shaders_inc/PostProcess.psh.h @@ -11,20 +11,21 @@ "{\n" " Color = g_ColorBuffer.Load(int3(PSIn.Pos.xy, 0));\n" "\n" -" float IsSelected0 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected1 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected2 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" +" float IsSelected0 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected1 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected2 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" "\n" -" float IsSelected3 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected4 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected5 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" +" float IsSelected3 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected4 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected5 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" "\n" -" float IsSelected6 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected7 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" -" float IsSelected8 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r < 0.0 ? +1.0 : -1.0;\n" +" float IsSelected6 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected7 = g_MeshId.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" +" float IsSelected8 = g_MeshId.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r < 0.0 ? -1.0 : +1.0;\n" "\n" " float Outline = IsSelected0 + IsSelected1 + IsSelected2 + IsSelected3 + IsSelected4 + IsSelected5 + IsSelected6 + IsSelected7 + IsSelected8;\n" -" Outline = saturate(1.0 - abs(Outline) / 9.0);\n" +" //Outline = (9.0 - Outline) * (Outline > 0.0 ? 1.0 / 8.0 : 0.0);\n" +" Outline = (Outline > 0.0 && Outline < 9.0) ? 1.0 : 0.0;\n" "\n" " Color.rgb += Outline * float3(0.25, 0.25, 0.1f);\n" "\n" diff --git a/Hydrogent/shaders_inc/shaders_list.h b/Hydrogent/shaders_inc/shaders_list.h index 435af5bf..cf596567 100644 --- a/Hydrogent/shaders_inc/shaders_list.h +++ b/Hydrogent/shaders_inc/shaders_list.h @@ -1,11 +1,15 @@ static const MemoryShaderSourceFileInfo g_Shaders[] = { { - "PostProcess.psh", - #include "PostProcess.psh.h" + "HnPostProcess.psh", + #include "HnPostProcess.psh.h" }, { - "PostProcess.vsh", - #include "PostProcess.vsh.h" + "HnPostProcess.vsh", + #include "HnPostProcess.vsh.h" + }, + { + "HnPostProcessStructures.fxh", + #include "HnPostProcessStructures.fxh.h" }, }; diff --git a/Hydrogent/src/HnRendererImpl.cpp b/Hydrogent/src/HnRendererImpl.cpp index 8f425471..061b1470 100644 --- a/Hydrogent/src/HnRendererImpl.cpp +++ b/Hydrogent/src/HnRendererImpl.cpp @@ -52,6 +52,7 @@ namespace HLSL namespace { #include "Shaders/PBR/public/PBR_Structures.fxh" +#include "../shaders/HnPostProcessStructures.fxh" } // namespace } // namespace HLSL @@ -71,6 +72,7 @@ HnRendererImpl::HnRendererImpl(IReferenceCounters* pRefCounters, m_Context{pContext}, m_CameraAttribsCB{CI.pCameraAttribsCB}, m_LightAttribsCB{CI.pLightAttribsCB}, + m_PostProcessAttribsCB{m_Device.CreateBuffer("Post process attribs CB", sizeof(HLSL::PostProcessAttribs))}, m_ConvertOutputToSRGB{CI.ConvertOutputToSRGB}, m_USDRenderer{ std::make_shared( @@ -307,7 +309,7 @@ void HnRendererImpl::PreparePostProcess(TEXTURE_FORMAT RTVFmt) { ShaderCI.Desc = {"Post process VS", SHADER_TYPE_VERTEX, true}; ShaderCI.EntryPoint = "main"; - ShaderCI.FilePath = "PostProcess.vsh"; + ShaderCI.FilePath = "HnPostProcess.vsh"; pVS = m_Device.CreateShader(ShaderCI); } @@ -316,7 +318,7 @@ void HnRendererImpl::PreparePostProcess(TEXTURE_FORMAT RTVFmt) { ShaderCI.Desc = {"Post process PS", SHADER_TYPE_PIXEL, true}; ShaderCI.EntryPoint = "main"; - ShaderCI.FilePath = "PostProcess.psh"; + ShaderCI.FilePath = "HnPostProcess.psh"; pPS = m_Device.CreateShader(ShaderCI); } @@ -337,6 +339,7 @@ void HnRendererImpl::PreparePostProcess(TEXTURE_FORMAT RTVFmt) .SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); m_PostProcess.PSO = m_Device.CreateGraphicsPipelineState(PsoCI); + m_PostProcess.PSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "cbPostProcessAttribs")->Set(m_PostProcessAttribsCB); m_PostProcess.PSO->CreateShaderResourceBinding(&m_PostProcess.SRB, true); } } @@ -383,17 +386,25 @@ void HnRendererImpl::Draw(IDeviceContext* pCtx, const HnDrawAttribs& Attribs) } RenderMeshes(pCtx, Attribs); + PerformPostProcess(pCtx, Attribs); +} + +void HnRendererImpl::PerformPostProcess(IDeviceContext* pCtx, const HnDrawAttribs& Attribs) +{ + ITextureView* pRTVs[] = {Attribs.pDstRTV}; + pCtx->SetRenderTargets(_countof(pRTVs), pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); { - ITextureView* pRTVs[] = {Attribs.pDstRTV}; - pCtx->SetRenderTargets(_countof(pRTVs), pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - - pCtx->SetPipelineState(m_PostProcess.PSO); - m_PostProcess.SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_ColorBuffer")->Set(m_ColorBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); - m_PostProcess.SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_MeshId")->Set(m_MeshIdTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); - pCtx->CommitShaderResources(m_PostProcess.SRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pCtx->Draw({3, DRAW_FLAG_VERIFY_ALL}); + MapHelper pDstShaderAttribs{pCtx, m_PostProcessAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD}; + pDstShaderAttribs->SelectionOutlineColor = Attribs.SlectionColor; + pDstShaderAttribs->NonselectionDesaturationFactor = Attribs.SelectedPrim != nullptr && !Attribs.SelectedPrim->IsEmpty() ? 0.5f : 0.f; } + + pCtx->SetPipelineState(m_PostProcess.PSO); + m_PostProcess.SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_ColorBuffer")->Set(m_ColorBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + m_PostProcess.SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_MeshId")->Set(m_MeshIdTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + pCtx->CommitShaderResources(m_PostProcess.SRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pCtx->Draw({3, DRAW_FLAG_VERIFY_ALL}); } void HnRendererImpl::RenderMesh(IDeviceContext* pCtx,