Add Quad Overdraw debug view mode
This commit is contained in:
158
Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
Normal file
158
Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "QuadOverdrawPass.h"
|
||||
#include "Engine/Engine/Time.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Assets/Material.h"
|
||||
#include "Engine/Level/Actors/Decal.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/RenderTargetPool.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
|
||||
void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, GPUTextureView* lightBuffer)
|
||||
{
|
||||
if (checkIfSkipPass())
|
||||
{
|
||||
context->Clear(lightBuffer, Color(0, Math::Sin(Time::Draw.UnscaledTime.GetTotalSeconds() * 5.0f) * 0.5f + 0.5f, 0, 1.0f));
|
||||
return;
|
||||
}
|
||||
PROFILE_GPU_CPU("Quad Overdraw");
|
||||
|
||||
// Setup resources
|
||||
const int32 width = renderContext.Buffers->GetWidth();
|
||||
const int32 height = renderContext.Buffers->GetHeight();
|
||||
auto tempDesc = GPUTextureDescription::New2D(width >> 1, height >> 1, PixelFormat::R32_UInt, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess);
|
||||
auto lockTexture = RenderTargetPool::Get(tempDesc);
|
||||
auto overdrawTexture = RenderTargetPool::Get(tempDesc);
|
||||
auto liveCountTexture = RenderTargetPool::Get(tempDesc);
|
||||
|
||||
// Clear buffers
|
||||
uint32 clearValueUINT[4] = { 0 };
|
||||
clearValueUINT[0] = 0xffffffff;
|
||||
context->ClearUA(lockTexture, clearValueUINT);
|
||||
clearValueUINT[0] = 0x00000000;
|
||||
context->ClearUA(overdrawTexture, clearValueUINT);
|
||||
context->ClearUA(liveCountTexture, clearValueUINT);
|
||||
context->ClearDepth(*renderContext.Buffers->DepthBuffer);
|
||||
|
||||
// Draw quad overdraw stats into UAVs
|
||||
context->BindUA(0, lockTexture->View());
|
||||
context->BindUA(1, overdrawTexture->View());
|
||||
context->BindUA(2, liveCountTexture->View());
|
||||
DrawCall drawCall;
|
||||
Platform::MemoryClear(&drawCall, sizeof(DrawCall));
|
||||
drawCall.PerInstanceRandom = 1.0f;
|
||||
MaterialBase::BindParameters bindParams(context, renderContext, drawCall);
|
||||
renderContext.View.Pass = DrawPass::QuadOverdraw;
|
||||
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, (GPUTextureView*)nullptr);
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer);
|
||||
auto boxModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/SimpleBox"));
|
||||
auto defaultMaterial = GPUDevice::Instance->GetDefaultMaterial();
|
||||
if (boxModel && boxModel->CanBeRendered() && defaultMaterial && defaultMaterial->IsReady())
|
||||
{
|
||||
// Draw decals
|
||||
for (int32 i = 0; i < renderContext.List->Decals.Count(); i++)
|
||||
{
|
||||
const auto decal = renderContext.List->Decals[i];
|
||||
ASSERT(decal && decal->Material);
|
||||
decal->GetWorld(&drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.PerInstanceRandom = decal->GetPerInstanceRandom();
|
||||
defaultMaterial->Bind(bindParams);
|
||||
boxModel->Render(context);
|
||||
}
|
||||
}
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBufferNoDecals);
|
||||
auto skyModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/Sphere"));
|
||||
auto skyMaterial = Content::LoadAsyncInternal<Material>(TEXT("Engine/SkyboxMaterial"));
|
||||
if (renderContext.List->Sky && skyModel && skyModel->CanBeRendered() && skyMaterial && skyMaterial->IsReady())
|
||||
{
|
||||
// Draw sky
|
||||
auto box = skyModel->GetBox();
|
||||
Matrix m1, m2;
|
||||
Matrix::Scaling(renderContext.View.Far / (box.GetSize().Y * 0.5f) * 0.95f, m1);
|
||||
Matrix::CreateWorld(renderContext.View.Position, Vector3::Up, Vector3::Backward, m2);
|
||||
m1 *= m2;
|
||||
drawCall.World = m1;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1);
|
||||
skyMaterial->Bind(bindParams);
|
||||
skyModel->Render(context);
|
||||
}
|
||||
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
|
||||
GPUTextureView* readOnlyDepthBuffer = depthBuffer->View();
|
||||
if (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView)
|
||||
readOnlyDepthBuffer = depthBuffer->ViewReadOnlyDepth();
|
||||
context->ResetSR();
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(readOnlyDepthBuffer, (GPUTextureView*)nullptr);
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Forward);
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Distortion);
|
||||
// TODO: draw volumetric particles
|
||||
context->ResetRenderTarget();
|
||||
context->ResetUA();
|
||||
context->ResetSR();
|
||||
|
||||
// Convert stats into debug colors
|
||||
context->BindSR(0, overdrawTexture->View());
|
||||
context->SetRenderTarget(lightBuffer);
|
||||
context->SetState(_ps);
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
// Free resources
|
||||
RenderTargetPool::Release(liveCountTexture);
|
||||
RenderTargetPool::Release(overdrawTexture);
|
||||
RenderTargetPool::Release(lockTexture);
|
||||
}
|
||||
|
||||
String QuadOverdrawPass::ToString() const
|
||||
{
|
||||
return TEXT("QuadOverdrawPass");
|
||||
}
|
||||
|
||||
void QuadOverdrawPass::Dispose()
|
||||
{
|
||||
// Base
|
||||
RendererPass::Dispose();
|
||||
|
||||
SAFE_DELETE_GPU_RESOURCE(_ps);
|
||||
_shader = nullptr;
|
||||
}
|
||||
|
||||
bool QuadOverdrawPass::setupResources()
|
||||
{
|
||||
if (GPUDevice::Instance->GetFeatureLevel() < FeatureLevel::SM5)
|
||||
return true;
|
||||
|
||||
if (!_shader)
|
||||
{
|
||||
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/Editor/QuadOverdraw"));
|
||||
if (!_shader)
|
||||
return true;
|
||||
#if COMPILE_WITH_DEV_ENV
|
||||
_shader.Get()->OnReloading.Bind<QuadOverdrawPass, &QuadOverdrawPass::OnShaderReloading>(this);
|
||||
#endif
|
||||
}
|
||||
if (!_shader->IsLoaded())
|
||||
return true;
|
||||
const auto shader = _shader->GetShader();
|
||||
|
||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
||||
if (!_ps)
|
||||
_ps = GPUDevice::Instance->CreatePipelineState();
|
||||
if (!_ps->IsValid())
|
||||
{
|
||||
psDesc.PS = shader->GetPS("PS");
|
||||
if (_ps->Init(psDesc))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user