Optimize decals rendering with depth test

#3599
This commit is contained in:
Wojtek Figat
2025-08-14 13:04:57 +02:00
parent 8a73d79936
commit cb92a2b8cb
2 changed files with 15 additions and 14 deletions

View File

@@ -47,7 +47,9 @@ void DecalMaterialShader::Bind(BindParameters& params)
MaterialParams::Bind(params.ParamsLink, bindMeta); MaterialParams::Bind(params.ParamsLink, bindMeta);
// Decals use depth buffer to draw on top of the objects // Decals use depth buffer to draw on top of the objects
context->BindSR(0, GET_TEXTURE_VIEW_SAFE(params.RenderContext.Buffers->DepthBuffer)); GPUTexture* depthBuffer = params.RenderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferView = EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->BindSR(0, depthBufferView);
// Setup material constants // Setup material constants
{ {
@@ -90,16 +92,20 @@ void DecalMaterialShader::Unload()
bool DecalMaterialShader::Load() bool DecalMaterialShader::Load()
{ {
GPUPipelineState::Description psDesc0 = GPUPipelineState::Description::DefaultNoDepth; GPUPipelineState::Description psDesc0 = GPUPipelineState::Description::DefaultNoDepth;
psDesc0.VS = _shader->GetVS("VS_Decal"); psDesc0.VS = _shader->GetVS("VS_Decal"); // TODO: move VS_Decal to be shared (eg. in GBuffer.shader)
if (psDesc0.VS == nullptr) if (psDesc0.VS == nullptr)
return true; return true;
psDesc0.PS = _shader->GetPS("PS_Decal"); psDesc0.PS = _shader->GetPS("PS_Decal");
psDesc0.CullMode = CullMode::Normal; psDesc0.CullMode = CullMode::Normal;
if (GPUDevice::Instance->Limits.HasReadOnlyDepth)
{
psDesc0.DepthEnable = true;
psDesc0.DepthWriteEnable = false;
}
switch (_info.DecalBlendingMode) switch (_info.DecalBlendingMode)
{ {
case MaterialDecalBlendingMode::Translucent: case MaterialDecalBlendingMode::Translucent:
{
psDesc0.BlendMode.BlendEnable = true; psDesc0.BlendMode.BlendEnable = true;
psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::SrcAlpha; psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::SrcAlpha;
psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha; psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha;
@@ -107,9 +113,7 @@ bool DecalMaterialShader::Load()
psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One; psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One;
psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB; psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB;
break; break;
}
case MaterialDecalBlendingMode::Stain: case MaterialDecalBlendingMode::Stain:
{
psDesc0.BlendMode.BlendEnable = true; psDesc0.BlendMode.BlendEnable = true;
psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::DestColor; psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::DestColor;
psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha; psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha;
@@ -117,9 +121,7 @@ bool DecalMaterialShader::Load()
psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One; psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One;
psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB; psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB;
break; break;
}
case MaterialDecalBlendingMode::Normal: case MaterialDecalBlendingMode::Normal:
{
psDesc0.BlendMode.BlendEnable = true; psDesc0.BlendMode.BlendEnable = true;
psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::SrcAlpha; psDesc0.BlendMode.SrcBlend = BlendingMode::Blend::SrcAlpha;
psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha; psDesc0.BlendMode.DestBlend = BlendingMode::Blend::InvSrcAlpha;
@@ -127,13 +129,10 @@ bool DecalMaterialShader::Load()
psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One; psDesc0.BlendMode.DestBlendAlpha = BlendingMode::Blend::One;
psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB; psDesc0.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB;
break; break;
}
case MaterialDecalBlendingMode::Emissive: case MaterialDecalBlendingMode::Emissive:
{
psDesc0.BlendMode = BlendingMode::Additive; psDesc0.BlendMode = BlendingMode::Additive;
break; break;
} }
}
_cache.Outside = GPUDevice::Instance->CreatePipelineState(); _cache.Outside = GPUDevice::Instance->CreatePipelineState();
if (_cache.Outside->Init(psDesc0)) if (_cache.Outside->Init(psDesc0))
@@ -143,6 +142,7 @@ bool DecalMaterialShader::Load()
} }
psDesc0.CullMode = CullMode::Inverted; psDesc0.CullMode = CullMode::Inverted;
psDesc0.DepthEnable = false;
_cache.Inside = GPUDevice::Instance->CreatePipelineState(); _cache.Inside = GPUDevice::Instance->CreatePipelineState();
if (_cache.Inside->Init(psDesc0)) if (_cache.Inside->Init(psDesc0))
{ {

View File

@@ -434,6 +434,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
PROFILE_GPU_CPU("Decals"); PROFILE_GPU_CPU("Decals");
auto context = GPUDevice::Instance->GetMainContext(); auto context = GPUDevice::Instance->GetMainContext();
auto buffers = renderContext.Buffers; auto buffers = renderContext.Buffers;
GPUTextureView* depthBuffer = EnumHasAnyFlags(buffers->DepthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? buffers->DepthBuffer->ViewReadOnlyDepth() : nullptr;
// Sort decals from the lowest order to the highest order // Sort decals from the lowest order to the highest order
Sorting::QuickSort(decals.Get(), decals.Count(), &SortDecal); Sorting::QuickSort(decals.Get(), decals.Count(), &SortDecal);
@@ -484,22 +485,22 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
count++; count++;
targetBuffers[2] = buffers->GBuffer1->View(); targetBuffers[2] = buffers->GBuffer1->View();
} }
context->SetRenderTarget(nullptr, ToSpan(targetBuffers, count)); context->SetRenderTarget(depthBuffer, ToSpan(targetBuffers, count));
break; break;
} }
case MaterialDecalBlendingMode::Stain: case MaterialDecalBlendingMode::Stain:
{ {
context->SetRenderTarget(buffers->GBuffer0->View()); context->SetRenderTarget(depthBuffer, buffers->GBuffer0->View());
break; break;
} }
case MaterialDecalBlendingMode::Normal: case MaterialDecalBlendingMode::Normal:
{ {
context->SetRenderTarget(buffers->GBuffer1->View()); context->SetRenderTarget(depthBuffer, buffers->GBuffer1->View());
break; break;
} }
case MaterialDecalBlendingMode::Emissive: case MaterialDecalBlendingMode::Emissive:
{ {
context->SetRenderTarget(lightBuffer); context->SetRenderTarget(depthBuffer, lightBuffer);
break; break;
} }
} }