Skip to content

Commit

Permalink
Hydrogent: reworked selection outline to use separate render target
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Oct 30, 2023
1 parent d0cf126 commit a59d857
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 45 deletions.
1 change: 1 addition & 0 deletions Hydrogent/interface/HnTokens.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace USD
(offscreenColorTarget) \
(finalColorTarget) \
(meshIdTarget) \
(selectionTarget) \
(depthBuffer)

// clang-format on
Expand Down
9 changes: 6 additions & 3 deletions Hydrogent/interface/Tasks/HnSetupRenderingTask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ struct HnSetupRenderingTaskParams
return !(*this == rhs);
}

TEXTURE_FORMAT ColorFormat = TEX_FORMAT_UNKNOWN;
TEXTURE_FORMAT MeshIdFormat = TEX_FORMAT_UNKNOWN;
TEXTURE_FORMAT DepthFormat = TEX_FORMAT_UNKNOWN;
TEXTURE_FORMAT ColorFormat = TEX_FORMAT_RGBA16_FLOAT;
TEXTURE_FORMAT MeshIdFormat = TEX_FORMAT_R32_FLOAT;
TEXTURE_FORMAT SelectionFormat = TEX_FORMAT_R8_UNORM;
TEXTURE_FORMAT DepthFormat = TEX_FORMAT_D32_FLOAT;

bool FrontFaceCCW = false;

Expand Down Expand Up @@ -140,6 +141,7 @@ class HnSetupRenderingTask final : public HnTask
pxr::SdfPath m_FinalColorTargetId;
pxr::SdfPath m_OffscreenColorTargetId;
pxr::SdfPath m_MeshIdTargetId;
pxr::SdfPath m_SelectionTargetId;
pxr::SdfPath m_DepthBufferId;

float4 m_ClearColor;
Expand All @@ -149,6 +151,7 @@ class HnSetupRenderingTask final : public HnTask

ITextureView* m_pFinalColorRTV = nullptr;
ITextureView* m_pMeshIdRTV = nullptr;
ITextureView* m_pSelectionRTV = nullptr;
ITextureView* m_pDepthDSV = nullptr;
};

Expand Down
23 changes: 11 additions & 12 deletions Hydrogent/shaders/HnPostProcess.psh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ cbuffer cbPostProcessAttribs
}

Texture2D g_ColorBuffer;
Texture2D g_MeshId;
Texture2D g_Selection;

void main(in PSInput PSIn,
out float4 Color : SV_Target0)
Expand All @@ -24,21 +24,20 @@ void main(in PSInput PSIn,
#endif

// Selected rprim is rendered with negative index
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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r;
float IsSelected1 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r;
float IsSelected2 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r;

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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r;
float IsSelected4 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r;
float IsSelected5 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r;

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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r;
float IsSelected7 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r;
float IsSelected8 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r;

float Outline = IsSelected0 + IsSelected1 + IsSelected2 + IsSelected3 + IsSelected4 + IsSelected5 + IsSelected6 + IsSelected7 + IsSelected8;
//Outline = (9.0 - Outline) * (Outline > 0.0 ? 1.0 / 8.0 : 0.0);
Outline = (Outline > 0.0 && Outline < 9.0) ? 1.0 : 0.0;
Outline = (Outline > 4.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));
Expand Down
23 changes: 11 additions & 12 deletions Hydrogent/shaders_inc/HnPostProcess.psh.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"}\n"
"\n"
"Texture2D g_ColorBuffer;\n"
"Texture2D g_MeshId;\n"
"Texture2D g_Selection;\n"
"\n"
"void main(in PSInput PSIn,\n"
" out float4 Color : SV_Target0)\n"
Expand All @@ -24,21 +24,20 @@
"#endif\n"
"\n"
" // Selected rprim is rendered with negative index\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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, -1.0), 0)).r;\n"
" float IsSelected1 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, -1.0), 0)).r;\n"
" float IsSelected2 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, -1.0), 0)).r;\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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, 0.0), 0)).r;\n"
" float IsSelected4 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, 0.0), 0)).r;\n"
" float IsSelected5 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, 0.0), 0)).r;\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_Selection.Load(int3(PSIn.Pos.xy + float2(-1.0, +1.0), 0)).r;\n"
" float IsSelected7 = g_Selection.Load(int3(PSIn.Pos.xy + float2( 0.0, +1.0), 0)).r;\n"
" float IsSelected8 = g_Selection.Load(int3(PSIn.Pos.xy + float2(+1.0, +1.0), 0)).r;\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"
" Outline = (Outline > 4.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"
Expand Down
26 changes: 26 additions & 0 deletions Hydrogent/src/HnRenderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ const pxr::TfTokenVector HnRenderDelegate::SupportedBPrimTypes =
};
// clang-format on

static std::string GetPbrPSMainSource(USD_Renderer::PSO_FLAGS PSOFlags)
{
VERIFY(PSOFlags & USD_Renderer::PSO_FLAG_ENABLE_CUSTOM_DATA_OUTPUT, "Custom output flag is expected to be set");
return R"(
struct PSOutput
{
float4 Color : SV_Target0;
float4 MeshID : SV_Target1;
float4 IsSelected : SV_Target2;
};
void main(in VSOutput VSOut,
in bool IsFrontFace : SV_IsFrontFace,
out PSOutput PSOut)
{
PSOut.Color = ComputePbrSurfaceColor(VSOut, IsFrontFace);
// It is important to set alpha to 1.0 as all targets are rendered with the same blend mode
PSOut.MeshID = float4(g_PBRAttribs.Renderer.CustomData.x, 0.0, 0.0, 1.0);
PSOut.IsSelected = float4(g_PBRAttribs.Renderer.CustomData.y, 0.0, 0.0, 1.0);
}
)";
}

HnRenderDelegate::HnRenderDelegate(const CreateInfo& CI) :
m_pDevice{CI.pDevice},
m_pContext{CI.pContext},
Expand Down Expand Up @@ -94,6 +118,8 @@ HnRenderDelegate::HnRenderDelegate(const CreateInfo& CI) :
USDRendererCI.InputLayout.LayoutElements = Inputs;
USDRendererCI.InputLayout.NumElements = _countof(Inputs);

USDRendererCI.GetPSMainSource = GetPbrPSMainSource;

return USDRendererCI;
}()),
},
Expand Down
10 changes: 6 additions & 4 deletions Hydrogent/src/HnRenderPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,12 @@ void HnRenderPass::RenderMesh(RenderState& State,
RendererParams.MiddleGray = 0.18f;
RendererParams.WhitePoint = 3.0f;

auto CustomData = float4{static_cast<float>(Mesh.GetUID()), 0, 0, 1};
if (Mesh.GetId().HasPrefix(m_Params.SelectedPrimId))
CustomData.x *= -1;
RendererParams.CustomData = CustomData;
RendererParams.CustomData = float4{
static_cast<float>(Mesh.GetUID()),
Mesh.GetId().HasPrefix(m_Params.SelectedPrimId) ? 1.f : 0.f,
0,
0,
};
}

State.pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
Expand Down
12 changes: 6 additions & 6 deletions Hydrogent/src/Tasks/HnPostProcessTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void HnPostProcessTask::PreparePSO(TEXTURE_FORMAT RTVFormat)
PipelineResourceLayoutDescX ResourceLauout;
ResourceLauout
.AddVariable(SHADER_TYPE_PIXEL, "g_ColorBuffer", SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
.AddVariable(SHADER_TYPE_PIXEL, "g_MeshId", SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
.AddVariable(SHADER_TYPE_PIXEL, "g_Selection", SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);

GraphicsPipelineStateCreateInfoX PsoCI{"Post process"};
PsoCI
Expand Down Expand Up @@ -229,8 +229,8 @@ void HnPostProcessTask::Execute(pxr::HdTaskContext* TaskCtx)
UNEXPECTED("Offscreen color RTV is not set in the task context");
return;
}
ITextureView* pMeshIdRTV = GetRenderBufferTarget(*m_RenderIndex, TaskCtx, HnRenderResourceTokens->meshIdTarget);
if (pMeshIdRTV == nullptr)
ITextureView* pSelectionRTV = GetRenderBufferTarget(*m_RenderIndex, TaskCtx, HnRenderResourceTokens->selectionTarget);
if (pSelectionRTV == nullptr)
{
UNEXPECTED("Mesh Id RTV is not set in the task context");
return;
Expand All @@ -241,8 +241,8 @@ void HnPostProcessTask::Execute(pxr::HdTaskContext* TaskCtx)
UNEXPECTED("Offscreen color SRV is null");
return;
}
ITextureView* pMeshIdSRV = pMeshIdRTV->GetTexture()->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
if (pMeshIdSRV == nullptr)
ITextureView* pSelectionSRV = pSelectionRTV->GetTexture()->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
if (pSelectionSRV == nullptr)
{
UNEXPECTED("Mesh Id SRV is null");
return;
Expand All @@ -269,7 +269,7 @@ void HnPostProcessTask::Execute(pxr::HdTaskContext* TaskCtx)
}
pCtx->SetPipelineState(m_PSO);
m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_ColorBuffer")->Set(pOffscreenColorSRV);
m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_MeshId")->Set(pMeshIdSRV);
m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_Selection")->Set(pSelectionSRV);
pCtx->CommitShaderResources(m_SRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->Draw({3, DRAW_FLAG_VERIFY_ALL});
}
Expand Down
2 changes: 1 addition & 1 deletion Hydrogent/src/Tasks/HnReadRprimIdTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void HnReadRprimIdTask::Execute(pxr::HdTaskContext* TaskCtx)
{
MappedTextureSubresource MappedData;
pCtx->MapTextureSubresource(pStagingTex, 0, 0, MAP_READ, MAP_FLAG_DO_NOT_WAIT, nullptr, MappedData);
m_MeshIndex = static_cast<Uint32>(std::abs(*static_cast<const float*>(MappedData.pData)));
m_MeshIndex = static_cast<Uint32>(*static_cast<const float*>(MappedData.pData));
pCtx->UnmapTextureSubresource(pStagingTex, 0, 0);
}
m_MeshIdReadBackQueue->Recycle(std::move(pStagingTex));
Expand Down
15 changes: 11 additions & 4 deletions Hydrogent/src/Tasks/HnSetupRenderingTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ HnSetupRenderingTask::HnSetupRenderingTask(pxr::HdSceneDelegate* ParamsDelegate,
};
m_OffscreenColorTargetId = InitBrim(HnRenderResourceTokens->offscreenColorTarget);
m_MeshIdTargetId = InitBrim(HnRenderResourceTokens->meshIdTarget);
m_SelectionTargetId = InitBrim(HnRenderResourceTokens->selectionTarget);
m_DepthBufferId = InitBrim(HnRenderResourceTokens->depthBuffer);
}

Expand All @@ -65,9 +66,10 @@ HnSetupRenderingTask::~HnSetupRenderingTask()
void HnSetupRenderingTask::UpdateRenderPassState(const HnSetupRenderingTaskParams& Params)
{
VERIFY_EXPR(Params.ColorFormat != TEX_FORMAT_UNKNOWN);
m_RenderPassState->SetNumRenderTargets(Params.MeshIdFormat != TEX_FORMAT_UNKNOWN ? 2 : 1);
m_RenderPassState->SetNumRenderTargets(3);
m_RenderPassState->SetRenderTargetFormat(0, Params.ColorFormat);
m_RenderPassState->SetRenderTargetFormat(1, Params.MeshIdFormat);
m_RenderPassState->SetRenderTargetFormat(2, Params.SelectionFormat);
m_RenderPassState->SetDepthStencilFormat(Params.DepthFormat);

m_RenderPassState->SetDepthBias(Params.DepthBias, Params.SlopeScaledDepthBias);
Expand Down Expand Up @@ -120,6 +122,8 @@ void HnSetupRenderingTask::PrepareRenderTargets(pxr::HdRenderIndex* RenderIndex,
if (Format == TEX_FORMAT_UNKNOWN)
return nullptr;

VERIFY_EXPR(!Id.IsEmpty());

HnRenderBuffer* Renderbuffer = static_cast<HnRenderBuffer*>(RenderIndex->GetBprim(pxr::HdPrimTypeTokens->renderBuffer, Id));
if (Renderbuffer == nullptr)
{
Expand Down Expand Up @@ -163,6 +167,7 @@ void HnSetupRenderingTask::PrepareRenderTargets(pxr::HdRenderIndex* RenderIndex,
};
m_pFinalColorRTV = UpdateBrim(m_OffscreenColorTargetId, m_RenderPassState->GetRenderTargetFormat(0), "Offscreen color target");
m_pMeshIdRTV = UpdateBrim(m_MeshIdTargetId, m_RenderPassState->GetRenderTargetFormat(1), "Mesh Id target");
m_pSelectionRTV = UpdateBrim(m_SelectionTargetId, m_RenderPassState->GetRenderTargetFormat(2), "Selection target");
m_pDepthDSV = UpdateBrim(m_DepthBufferId, m_RenderPassState->GetDepthStencilFormat(), "Depth buffer");
}

Expand All @@ -173,6 +178,7 @@ void HnSetupRenderingTask::Prepare(pxr::HdTaskContext* TaskCtx,
(*TaskCtx)[HnRenderResourceTokens->finalColorTarget] = pxr::VtValue{m_FinalColorTargetId};
(*TaskCtx)[HnRenderResourceTokens->offscreenColorTarget] = pxr::VtValue{m_OffscreenColorTargetId};
(*TaskCtx)[HnRenderResourceTokens->meshIdTarget] = pxr::VtValue{m_MeshIdTargetId};
(*TaskCtx)[HnRenderResourceTokens->selectionTarget] = pxr::VtValue{m_SelectionTargetId};

if (ITextureView* pFinalColorRTV = GetRenderBufferTarget(*RenderIndex, m_FinalColorTargetId))
{
Expand All @@ -194,14 +200,15 @@ void HnSetupRenderingTask::Execute(pxr::HdTaskContext* TaskCtx)
return;
}

ITextureView* pRTVs[] = {m_pFinalColorRTV, m_pMeshIdRTV};
ITextureView* pRTVs[] = {m_pFinalColorRTV, m_pMeshIdRTV, m_pSelectionRTV};

auto* pCtx = static_cast<HnRenderDelegate*>(m_RenderIndex->GetRenderDelegate())->GetDeviceContext();

pCtx->SetRenderTargets(_countof(pRTVs), pRTVs, m_pDepthDSV, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->ClearRenderTarget(pRTVs[0], m_ClearColor.Data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->ClearRenderTarget(m_pFinalColorRTV, m_ClearColor.Data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
constexpr float Zero[] = {0, 0, 0, 0};
pCtx->ClearRenderTarget(pRTVs[1], Zero, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->ClearRenderTarget(m_pMeshIdRTV, Zero, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->ClearRenderTarget(m_pSelectionRTV, Zero, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->ClearDepthStencil(m_pDepthDSV, CLEAR_DEPTH_FLAG, m_ClearDepth, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->SetStencilRef(m_RenderPassState->GetStencilRef());
}
Expand Down
2 changes: 1 addition & 1 deletion PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class PBR_Renderer
/// An optional user-provided callback function that is used to generate the pixel
/// shader's main function source code for the specified PSO flags. If null, the renderer
/// will use the default implementation.
std::function<std::string(PSO_FLAGS PsoFlags)> GetPSMainShaderSource = nullptr;
std::function<std::string(PSO_FLAGS PsoFlags)> GetPSMainSource = nullptr;
};

enum ALPHA_MODE
Expand Down
4 changes: 2 additions & 2 deletions PBR/src/PBR_Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,9 +818,9 @@ void PBR_Renderer::CreateShaders(PSO_FLAGS PSOFlags,

std::string PSMainSource;

if (m_Settings.GetPSMainShaderSource)
if (m_Settings.GetPSMainSource)
{
PSMainSource = m_Settings.GetPSMainShaderSource(PSOFlags);
PSMainSource = m_Settings.GetPSMainSource(PSOFlags);
}
else
{
Expand Down

0 comments on commit a59d857

Please sign in to comment.