159 lines
6.0 KiB
C++
159 lines
6.0 KiB
C++
// 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
|