Hair - ShortCut rendering technique and pipeline with Marschner lighting model (#4871)
- This rendering technique reduces the memory required per pipeline by 750MB compared to the PPLL technique!! - Using 3 screen buffers representing the closest 3 hair gragments depths. - Going through second geometry pass that disqualify any fragment further than the third depth, the technique blends the three closes shaders hair fragments. - Supports the Marschner lighting model (big change from the original TressFX 4.1 implementation) - The current technique is almost twice the performance of the PPLL but not quite as advacned when come to final visual quality. Remarks: Unlike the PPLL, this technique is still lacking some of the advanced features added to the PPLL such as 1. Back lobe (TT) conseal by depth comparison 2. Thickness dependency in light transfer (mainly TT) 3. Allowing TT transfer for thin separated hair strands (might be supported by default with no distinction) Signed-off-by: Adi-Amazon <Adi Bar-Lev 82479970+Adi-Amazon@users.noreply.github.com> Signed-off-by: Adi-Amazon <Adi Bar-Lev barlev@amazon.com> Signed-off-by: Adi-Amazon <Adi Bar-Lev 82479970+Adi-Amazon@users.noreply.github.com> Signed-off-by: Adi-Amazon <Adi Bar-Lev barlev@amazon.com> Co-authored-by: Adi-Amazon <Adi Bar-Lev 82479970+Adi-Amazon@users.noreply.github.com>
This commit is contained in:
@@ -993,7 +993,7 @@ namespace AZ
|
||||
//-------------------------------------
|
||||
// Dynamic buffers, data and Srg creation - shared between passes and changed on the GPU
|
||||
if (!m_dynamicHairData.CreateDynamicGPUResources(
|
||||
m_skinningShader, m_PPLLFillShader,
|
||||
m_skinningShader, m_geometryRasterShader,
|
||||
m_NumTotalVertices, m_NumTotalStrands))
|
||||
{
|
||||
AZ_Error("Hair Gem", false, "Hair - Error creating dynamic resources [%s]", assetName );
|
||||
@@ -1028,7 +1028,7 @@ namespace AZ
|
||||
|
||||
// Rendering setup
|
||||
bool renderResourcesSuccess;
|
||||
renderResourcesSuccess = CreateRenderingGPUResources(m_PPLLFillShader, *asset, assetName);
|
||||
renderResourcesSuccess = CreateRenderingGPUResources(m_geometryRasterShader, *asset, assetName);
|
||||
renderResourcesSuccess &= PopulateDrawStrandsBindSet(renderSettings);
|
||||
renderResourcesSuccess &= UploadRenderingGPUResources(*asset);
|
||||
|
||||
@@ -1057,17 +1057,10 @@ namespace AZ
|
||||
}
|
||||
|
||||
{
|
||||
Data::Instance<HairPPLLRasterPass> rasterPass = m_featureProcessor->GetHairPPLLRasterPass();
|
||||
if (!rasterPass.get())
|
||||
m_geometryRasterShader = m_featureProcessor->GetGeometryRasterShader();
|
||||
if (!m_geometryRasterShader)
|
||||
{
|
||||
AZ_Error("Hair Gem", false, "Failed to get PPLL raster fill Pass.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_PPLLFillShader = rasterPass->GetShader();
|
||||
if (!m_PPLLFillShader)
|
||||
{
|
||||
AZ_Error("Hair Gem", false, "Failed to get hair raster fill shader from raster pass");
|
||||
AZ_Error("Hair Gem", false, "Failed to get hair geometry raster shader");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1116,7 +1109,7 @@ namespace AZ
|
||||
return updatedCB;
|
||||
}
|
||||
|
||||
bool HairRenderObject::BuildPPLLDrawPacket(RHI::DrawPacketBuilder::DrawRequest& drawRequest)
|
||||
bool HairRenderObject::BuildDrawPacket(RPI::Shader* geometryShader, RHI::DrawPacketBuilder::DrawRequest& drawRequest)
|
||||
{
|
||||
RHI::DrawPacketBuilder drawPacketBuilder;
|
||||
RHI::DrawIndexed drawIndexed;
|
||||
@@ -1159,21 +1152,38 @@ namespace AZ
|
||||
drawPacketBuilder.AddShaderResourceGroup(simSrg->GetRHIShaderResourceGroup());
|
||||
drawPacketBuilder.AddDrawItem(drawRequest);
|
||||
|
||||
if (m_fillDrawPacket)
|
||||
{
|
||||
delete m_fillDrawPacket;
|
||||
}
|
||||
m_fillDrawPacket = drawPacketBuilder.End();
|
||||
|
||||
if (!m_fillDrawPacket)
|
||||
const RHI::DrawPacket* drawPacket = drawPacketBuilder.End();
|
||||
if (!drawPacket)
|
||||
{
|
||||
AZ_Error("Hair Gem", false, "Failed to build the hair DrawPacket.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert the newly created draw packet to the map based on its shader
|
||||
auto iter = m_geometryDrawPackets.find(geometryShader);
|
||||
if (iter != m_geometryDrawPackets.end())
|
||||
{
|
||||
delete iter->second;
|
||||
iter->second = drawPacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_geometryDrawPackets[geometryShader] = drawPacket;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const RHI::DrawPacket* HairRenderObject::GetGeometrylDrawPacket(RPI::Shader* geometryShader)
|
||||
{
|
||||
auto iter = m_geometryDrawPackets.find(geometryShader);
|
||||
if (iter == m_geometryDrawPackets.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
const RHI::DispatchItem* HairRenderObject::GetDispatchItem(RPI::Shader* computeShader)
|
||||
{
|
||||
auto dispatchIter = m_dispatchItems.find(computeShader);
|
||||
@@ -1210,4 +1220,3 @@ namespace AZ
|
||||
} // namespace Hair
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
|
||||
Reference in New Issue
Block a user