e81baa9fef
Big renderer refactor to remove some global state. - Renderer no longer uses "global scene", but instead takes scene as parameter to functions - Visibility is exposed, user can generate visibility for arbitrary camera and some exposed parameters - Big changes in renderer can make user render code in high level interface not compatible with previous versions - Fixed occlusion culling const correctness
1401 lines
45 KiB
C++
1401 lines
45 KiB
C++
#include "RenderPath3D.h"
|
|
#include "wiRenderer.h"
|
|
#include "wiImage.h"
|
|
#include "wiHelper.h"
|
|
#include "wiTextureHelper.h"
|
|
#include "ResourceMapping.h"
|
|
#include "wiProfiler.h"
|
|
|
|
using namespace wiGraphics;
|
|
|
|
void RenderPath3D::ResizeBuffers()
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
FORMAT defaultTextureFormat = device->GetBackBufferFormat();
|
|
|
|
|
|
// Render targets:
|
|
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
if (getMSAASampleCount() == 1)
|
|
{
|
|
desc.BindFlags |= BIND_UNORDERED_ACCESS;
|
|
}
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
|
|
desc.Format = FORMAT_R8G8B8A8_UNORM;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_ALBEDO_ROUGHNESS]);
|
|
device->SetName(&rtGbuffer[GBUFFER_ALBEDO_ROUGHNESS], "rtGbuffer[GBUFFER_ALBEDO_ROUGHNESS]");
|
|
|
|
desc.Format = FORMAT_R16G16B16A16_FLOAT;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_NORMAL_VELOCITY]);
|
|
device->SetName(&rtGbuffer[GBUFFER_NORMAL_VELOCITY], "rtGbuffer[GBUFFER_NORMAL_VELOCITY]");
|
|
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_LIGHTBUFFER_DIFFUSE]);
|
|
device->SetName(&rtGbuffer[GBUFFER_LIGHTBUFFER_DIFFUSE], "rtGbuffer[GBUFFER_LIGHTBUFFER_DIFFUSE]");
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_LIGHTBUFFER_SPECULAR]);
|
|
device->SetName(&rtGbuffer[GBUFFER_LIGHTBUFFER_SPECULAR], "rtGbuffer[GBUFFER_LIGHTBUFFER_SPECULAR]");
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.SampleCount = 1;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
|
|
desc.Format = FORMAT_R8G8B8A8_UNORM;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_ALBEDO_ROUGHNESS]);
|
|
device->SetName(&rtGbuffer_resolved[GBUFFER_ALBEDO_ROUGHNESS], "rtGbuffer_resolved[GBUFFER_ALBEDO_ROUGHNESS]");
|
|
|
|
desc.Format = FORMAT_R16G16B16A16_FLOAT;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_NORMAL_VELOCITY]);
|
|
device->SetName(&rtGbuffer_resolved[GBUFFER_NORMAL_VELOCITY], "rtGbuffer_resolved[GBUFFER_NORMAL_VELOCITY]");
|
|
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_DIFFUSE]);
|
|
device->SetName(&rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_DIFFUSE], "rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_DIFFUSE]");
|
|
device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_SPECULAR]);
|
|
device->SetName(&rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_SPECULAR], "rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_SPECULAR]");
|
|
}
|
|
|
|
if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE))
|
|
{
|
|
desc.BindFlags |= BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.SampleCount = 1;
|
|
|
|
device->CreateTexture(&desc, nullptr, &rtDiffuseTemporal[0]);
|
|
device->SetName(&rtDiffuseTemporal[0], "rtDiffuseTemporal[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtDiffuseTemporal[1]);
|
|
device->SetName(&rtDiffuseTemporal[1], "rtDiffuseTemporal[1]");
|
|
|
|
device->CreateTexture(&desc, nullptr, &rtSpecularTemporal[0]);
|
|
device->SetName(&rtSpecularTemporal[0], "rtSpecularTemporal[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtSpecularTemporal[1]);
|
|
device->SetName(&rtSpecularTemporal[1], "rtSpecularTemporal[1]");
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
if (getMSAASampleCount() == 1)
|
|
{
|
|
desc.BindFlags |= BIND_UNORDERED_ACCESS;
|
|
}
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
device->CreateTexture(&desc, nullptr, &rtDeferred);
|
|
device->SetName(&rtDeferred, "rtDeferred");
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.SampleCount = 1;
|
|
desc.BindFlags |= BIND_UNORDERED_ACCESS;
|
|
|
|
device->CreateTexture(&desc, nullptr, &rtDeferred_resolved);
|
|
device->SetName(&rtDeferred_resolved, "rtDeferred_resolved");
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
device->CreateTexture(&desc, nullptr, &rtSSS[0]);
|
|
device->SetName(&rtSSS[0], "rtSSS[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtSSS[1]);
|
|
device->SetName(&rtSSS[1], "rtSSS[1]");
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.SampleCount = 1;
|
|
|
|
device->CreateTexture(&desc, nullptr, &rtSSS_resolved);
|
|
device->SetName(&rtSSS_resolved, "rtSSS_resolved");
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R16G16B16A16_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtSSR);
|
|
device->SetName(&rtSSR, "rtSSR");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
desc.Format = FORMAT_R16G16B16A16_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
device->CreateTexture(&desc, nullptr, &rtParticleDistortion);
|
|
device->SetName(&rtParticleDistortion, "rtParticleDistortion");
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.SampleCount = 1;
|
|
device->CreateTexture(&desc, nullptr, &rtParticleDistortion_Resolved);
|
|
device->SetName(&rtParticleDistortion_Resolved, "rtParticleDistortion_Resolved");
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.Format = FORMAT_R16G16B16A16_FLOAT;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 4;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 4;
|
|
device->CreateTexture(&desc, nullptr, &rtVolumetricLights[0]);
|
|
device->SetName(&rtVolumetricLights[0], "rtVolumetricLights[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtVolumetricLights[1]);
|
|
device->SetName(&rtVolumetricLights[1], "rtVolumetricLights[1]");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
desc.Format = FORMAT_R8G8B8A8_SNORM;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtWaterRipple);
|
|
device->SetName(&rtWaterRipple, "rtWaterRipple");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS | BIND_RENDER_TARGET;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 2;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 2;
|
|
desc.MipLevels = std::min(8u, (uint32_t)std::log2(std::max(desc.Width, desc.Height)));
|
|
device->CreateTexture(&desc, nullptr, &rtSceneCopy);
|
|
device->SetName(&rtSceneCopy, "rtSceneCopy");
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
device->CreateTexture(&desc, nullptr, &rtSceneCopy_tmp);
|
|
device->SetName(&rtSceneCopy_tmp, "rtSceneCopy_tmp");
|
|
|
|
for (uint32_t i = 0; i < rtSceneCopy.GetDesc().MipLevels; ++i)
|
|
{
|
|
int subresource_index;
|
|
subresource_index = device->CreateSubresource(&rtSceneCopy, SRV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtSceneCopy_tmp, SRV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtSceneCopy, UAV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtSceneCopy_tmp, UAV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 4;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 4;
|
|
desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE;
|
|
device->CreateTexture(&desc, nullptr, &rtReflection);
|
|
device->SetName(&rtReflection, "rtReflection");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R8_UNORM;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtAO);
|
|
device->SetName(&rtAO, "rtAO");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
|
|
desc.Format = defaultTextureFormat;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
device->CreateTexture(&desc, nullptr, &rtSun[0]);
|
|
device->SetName(&rtSun[0], "rtSun[0]");
|
|
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.SampleCount = 1;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 2;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 2;
|
|
device->CreateTexture(&desc, nullptr, &rtSun[1]);
|
|
device->SetName(&rtSun[1], "rtSun[1]");
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.SampleCount = 1;
|
|
device->CreateTexture(&desc, nullptr, &rtSun_resolved);
|
|
device->SetName(&rtSun_resolved, "rtSun_resolved");
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 4;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 4;
|
|
desc.MipLevels = std::min(5u, (uint32_t)std::log2(std::max(desc.Width, desc.Height)));
|
|
device->CreateTexture(&desc, nullptr, &rtBloom);
|
|
device->SetName(&rtBloom, "rtBloom");
|
|
device->CreateTexture(&desc, nullptr, &rtBloom_tmp);
|
|
device->SetName(&rtBloom_tmp, "rtBloom_tmp");
|
|
|
|
for (uint32_t i = 0; i < rtBloom.GetDesc().MipLevels; ++i)
|
|
{
|
|
int subresource_index;
|
|
subresource_index = device->CreateSubresource(&rtBloom, SRV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtBloom_tmp, SRV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtBloom, UAV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtBloom_tmp, UAV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtTemporalAA[0]);
|
|
device->SetName(&rtTemporalAA[0], "rtTemporalAA[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtTemporalAA[1]);
|
|
device->SetName(&rtTemporalAA[1], "rtTemporalAA[1]");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R11G11B10_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtPostprocess_HDR);
|
|
device->SetName(&rtPostprocess_HDR, "rtPostprocess_HDR");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = defaultTextureFormat;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
device->CreateTexture(&desc, nullptr, &rtPostprocess_LDR[0]);
|
|
device->SetName(&rtPostprocess_LDR[0], "rtPostprocess_LDR[0]");
|
|
device->CreateTexture(&desc, nullptr, &rtPostprocess_LDR[1]);
|
|
device->SetName(&rtPostprocess_LDR[1], "rtPostprocess_LDR[1]");
|
|
|
|
desc.Width /= 4;
|
|
desc.Height /= 4;
|
|
desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE;
|
|
device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[0]);
|
|
device->SetName(&rtGUIBlurredBackground[0], "rtGUIBlurredBackground[0]");
|
|
|
|
desc.Width /= 4;
|
|
desc.Height /= 4;
|
|
device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[1]);
|
|
device->SetName(&rtGUIBlurredBackground[1], "rtGUIBlurredBackground[1]");
|
|
device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[2]);
|
|
device->SetName(&rtGUIBlurredBackground[2], "rtGUIBlurredBackground[2]");
|
|
}
|
|
|
|
if(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2))
|
|
{
|
|
uint32_t tileSize = device->GetVariableRateShadingTileSize();
|
|
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R8_UINT;
|
|
desc.Width = (wiRenderer::GetInternalResolution().x + tileSize - 1) / tileSize;
|
|
desc.Height = (wiRenderer::GetInternalResolution().y + tileSize - 1) / tileSize;
|
|
device->CreateTexture(&desc, nullptr, &rtShadingRate);
|
|
device->SetName(&rtShadingRate, "rtShadingRate");
|
|
}
|
|
|
|
// Depth buffers:
|
|
{
|
|
TextureDesc desc;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
|
|
desc.Format = FORMAT_R32G8X24_TYPELESS;
|
|
desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE;
|
|
desc.SampleCount = getMSAASampleCount();
|
|
desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL_READONLY;
|
|
device->CreateTexture(&desc, nullptr, &depthBuffer);
|
|
device->SetName(&depthBuffer, "depthBuffer");
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.Format = FORMAT_R32_FLOAT;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
}
|
|
else
|
|
{
|
|
desc.Format = FORMAT_R32G8X24_TYPELESS;
|
|
}
|
|
desc.SampleCount = 1;
|
|
desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE;
|
|
device->CreateTexture(&desc, nullptr, &depthBuffer_Copy);
|
|
device->SetName(&depthBuffer_Copy, "depthBuffer_Copy");
|
|
device->CreateTexture(&desc, nullptr, &depthBuffer_Copy1);
|
|
device->SetName(&depthBuffer_Copy1, "depthBuffer_Copy1");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_DEPTH_STENCIL;
|
|
desc.Format = FORMAT_D16_UNORM;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 4;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 4;
|
|
desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL;
|
|
device->CreateTexture(&desc, nullptr, &depthBuffer_Reflection);
|
|
device->SetName(&depthBuffer_Reflection, "depthBuffer_Reflection");
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
|
desc.Format = FORMAT_R32_FLOAT;
|
|
desc.Width = wiRenderer::GetInternalResolution().x;
|
|
desc.Height = wiRenderer::GetInternalResolution().y;
|
|
desc.MipLevels = 6;
|
|
device->CreateTexture(&desc, nullptr, &rtLinearDepth);
|
|
device->SetName(&rtLinearDepth, "rtLinearDepth");
|
|
|
|
for (uint32_t i = 0; i < desc.MipLevels; ++i)
|
|
{
|
|
int subresource_index;
|
|
subresource_index = device->CreateSubresource(&rtLinearDepth, SRV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
subresource_index = device->CreateSubresource(&rtLinearDepth, UAV, 0, 1, i, 1);
|
|
assert(subresource_index == i);
|
|
}
|
|
}
|
|
{
|
|
TextureDesc desc;
|
|
desc.BindFlags = BIND_DEPTH_STENCIL;
|
|
desc.Format = FORMAT_D16_UNORM;
|
|
desc.Width = wiRenderer::GetInternalResolution().x / 4;
|
|
desc.Height = wiRenderer::GetInternalResolution().y / 4;
|
|
desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL_READONLY;
|
|
device->CreateTexture(&desc, nullptr, &smallDepth);
|
|
device->SetName(&smallDepth, "smallDepth");
|
|
}
|
|
|
|
// Render passes:
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_CLEAR,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
device->CreateRenderPass(&desc, &renderpass_depthprepass);
|
|
|
|
desc.attachments.clear();
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_ALBEDO_ROUGHNESS], RenderPassAttachment::LOADOP_DONTCARE));
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_NORMAL_VELOCITY], RenderPassAttachment::LOADOP_CLEAR));
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_LIGHTBUFFER_DIFFUSE], RenderPassAttachment::LOADOP_CLEAR));
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_LIGHTBUFFER_SPECULAR], RenderPassAttachment::LOADOP_CLEAR));
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_ALBEDO_ROUGHNESS)));
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY)));
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_LIGHTBUFFER_DIFFUSE)));
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_LIGHTBUFFER_SPECULAR)));
|
|
}
|
|
device->CreateRenderPass(&desc, &renderpass_main);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtDeferred, RenderPassAttachment::LOADOP_LOAD));
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetDeferred_Read()));
|
|
}
|
|
device->CreateRenderPass(&desc, &renderpass_transparent);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtDeferred, RenderPassAttachment::LOADOP_LOAD));
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_NORMAL_VELOCITY], RenderPassAttachment::LOADOP_LOAD));
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetDeferred_Read()));
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY)));
|
|
}
|
|
device->CreateRenderPass(&desc, &renderpass_deferredcomposition);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_LIGHTBUFFER_DIFFUSE], RenderPassAttachment::LOADOP_LOAD));
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(&rtGbuffer_resolved[GBUFFER_LIGHTBUFFER_DIFFUSE]));
|
|
}
|
|
device->CreateRenderPass(&desc, &renderpass_SSS[0]);
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.back() = RenderPassAttachment::Resolve(&rtSSS_resolved);
|
|
}
|
|
desc.attachments[0].texture = &rtSSS[0];
|
|
device->CreateRenderPass(&desc, &renderpass_SSS[1]);
|
|
|
|
desc.attachments[0].texture = &rtSSS[1];
|
|
device->CreateRenderPass(&desc, &renderpass_SSS[2]);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&smallDepth,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_DONTCARE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_occlusionculling);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::RenderTarget(
|
|
&rtReflection,
|
|
RenderPassAttachment::LOADOP_DONTCARE,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_SHADER_RESOURCE,
|
|
IMAGE_LAYOUT_RENDERTARGET,
|
|
IMAGE_LAYOUT_SHADER_RESOURCE
|
|
)
|
|
);
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer_Reflection,
|
|
RenderPassAttachment::LOADOP_CLEAR,
|
|
RenderPassAttachment::STOREOP_DONTCARE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL
|
|
)
|
|
);
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_reflection);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&smallDepth,
|
|
RenderPassAttachment::LOADOP_DONTCARE,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_downsampledepthbuffer);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtSceneCopy, RenderPassAttachment::LOADOP_DONTCARE));
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_downsamplescene);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtSun[0], RenderPassAttachment::LOADOP_CLEAR));
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.back().storeop = RenderPassAttachment::STOREOP_DONTCARE;
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(&rtSun_resolved));
|
|
}
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_lightshafts);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtVolumetricLights[0], RenderPassAttachment::LOADOP_CLEAR));
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_volumetriclight);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtParticleDistortion, RenderPassAttachment::LOADOP_CLEAR));
|
|
desc.attachments.push_back(
|
|
RenderPassAttachment::DepthStencil(
|
|
&depthBuffer,
|
|
RenderPassAttachment::LOADOP_LOAD,
|
|
RenderPassAttachment::STOREOP_STORE,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,
|
|
IMAGE_LAYOUT_DEPTHSTENCIL_READONLY
|
|
)
|
|
);
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
desc.attachments.push_back(RenderPassAttachment::Resolve(&rtParticleDistortion_Resolved));
|
|
}
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_particledistortion);
|
|
}
|
|
{
|
|
RenderPassDesc desc;
|
|
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtWaterRipple, RenderPassAttachment::LOADOP_CLEAR));
|
|
|
|
device->CreateRenderPass(&desc, &renderpass_waterripples);
|
|
}
|
|
|
|
RenderPath2D::ResizeBuffers();
|
|
}
|
|
|
|
void RenderPath3D::Update(float dt)
|
|
{
|
|
RenderPath2D::Update(dt);
|
|
|
|
scene->Update(dt * wiRenderer::GetGameSpeed());
|
|
|
|
// Frustum culling for main camera:
|
|
visibility_main.scene = scene;
|
|
visibility_main.camera = &wiRenderer::GetCamera();
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_OBJECTS;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_LIGHTS;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_DECALS;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_ENVPROBES;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_EMITTERS;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_HAIRS;
|
|
visibility_main.flags |= wiRenderer::Visibility::ALLOW_REQUEST_REFLECTION;
|
|
wiRenderer::UpdateVisibility(visibility_main, getLayerMask());
|
|
|
|
if (visibility_main.planar_reflection_visible)
|
|
{
|
|
// Frustum culling for planar reflections:
|
|
visibility_reflection.scene = scene;
|
|
visibility_reflection.camera = &wiRenderer::GetRefCamera();
|
|
visibility_reflection.flags |= wiRenderer::Visibility::ALLOW_OBJECTS;
|
|
wiRenderer::UpdateVisibility(visibility_reflection, getLayerMask());
|
|
}
|
|
|
|
wiRenderer::OcclusionCulling_Read(*scene, visibility_main);
|
|
wiRenderer::UpdatePerFrameData(*scene, visibility_main, dt);
|
|
|
|
std::swap(depthBuffer_Copy, depthBuffer_Copy1);
|
|
}
|
|
|
|
void RenderPath3D::Render() const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
wiJobSystem::context ctx;
|
|
CommandList cmd;
|
|
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) { RenderFrameSetUp(cmd); });
|
|
|
|
if (getShadowsEnabled() && !wiRenderer::GetRaytracedShadowsEnabled())
|
|
{
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) {
|
|
wiRenderer::DrawShadowmaps(visibility_main, cmd, getLayerMask());
|
|
});
|
|
}
|
|
|
|
if (wiRenderer::GetVoxelRadianceEnabled())
|
|
{
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [cmd, this](wiJobArgs args) {
|
|
wiRenderer::VoxelRadiance(visibility_main, cmd);
|
|
});
|
|
}
|
|
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [cmd, this](wiJobArgs args) {
|
|
wiRenderer::BindCommonResources(cmd);
|
|
wiRenderer::RefreshDecalAtlas(wiScene::GetScene(), cmd);
|
|
wiRenderer::RefreshLightmapAtlas(wiScene::GetScene(), cmd);
|
|
wiRenderer::RefreshEnvProbes(visibility_main, cmd);
|
|
wiRenderer::RefreshImpostors(wiScene::GetScene(), cmd);
|
|
});
|
|
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) { RenderReflections(cmd); });
|
|
|
|
|
|
static const uint32_t drawscene_flags =
|
|
wiRenderer::DRAWSCENE_OPAQUE |
|
|
wiRenderer::DRAWSCENE_HAIRPARTICLE |
|
|
wiRenderer::DRAWSCENE_TESSELLATION |
|
|
wiRenderer::DRAWSCENE_OCCLUSIONCULLING
|
|
;
|
|
|
|
// Main scene:
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) {
|
|
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
wiRenderer::UpdateCameraCB(wiRenderer::GetCamera(), cmd);
|
|
|
|
// depth prepass
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("Z-Prepass", cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_depthprepass, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)depthBuffer.GetDesc().Width;
|
|
vp.Height = (float)depthBuffer.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DrawScene(visibility_main, RENDERPASS_DEPTHONLY, cmd, drawscene_flags);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
|
|
if (getMSAASampleCount() > 1)
|
|
{
|
|
{
|
|
GPUBarrier barriers[] = {
|
|
GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_SHADER_RESOURCE),
|
|
GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_GENERAL)
|
|
};
|
|
device->Barrier(barriers, arraysize(barriers), cmd);
|
|
}
|
|
|
|
wiRenderer::ResolveMSAADepthBuffer(depthBuffer_Copy, depthBuffer, cmd);
|
|
|
|
{
|
|
GPUBarrier barriers[] = {
|
|
GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY),
|
|
GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_GENERAL, IMAGE_LAYOUT_SHADER_RESOURCE)
|
|
};
|
|
device->Barrier(barriers, arraysize(barriers), cmd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
{
|
|
GPUBarrier barriers[] = {
|
|
GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_COPY_SRC),
|
|
GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_COPY_DST)
|
|
};
|
|
device->Barrier(barriers, arraysize(barriers), cmd);
|
|
}
|
|
|
|
device->CopyResource(&depthBuffer_Copy, &depthBuffer, cmd);
|
|
|
|
{
|
|
GPUBarrier barriers[] = {
|
|
GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_COPY_SRC, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY),
|
|
GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_COPY_DST, IMAGE_LAYOUT_SHADER_RESOURCE)
|
|
};
|
|
device->Barrier(barriers, arraysize(barriers), cmd);
|
|
}
|
|
}
|
|
|
|
RenderLinearDepth(cmd);
|
|
|
|
RenderAO(cmd);
|
|
});
|
|
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) {
|
|
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
wiRenderer::ComputeTiledLightCulling(
|
|
depthBuffer_Copy,
|
|
cmd
|
|
);
|
|
|
|
if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2))
|
|
{
|
|
wiRenderer::ComputeShadingRateClassification(GetGbuffer_Read(), rtLinearDepth, rtShadingRate, cmd);
|
|
device->BindShadingRate(SHADING_RATE_1X1, cmd);
|
|
device->BindShadingRateImage(&rtShadingRate, cmd);
|
|
}
|
|
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
|
|
// Opaque scene:
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("Opaque Scene", cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_main, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)depthBuffer.GetDesc().Width;
|
|
vp.Height = (float)depthBuffer.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
device->BindResource(PS, getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd);
|
|
device->BindResource(PS, getAOEnabled() ? &rtAO : wiTextureHelper::getWhite(), TEXSLOT_RENDERPATH_AO, cmd);
|
|
device->BindResource(PS, getSSREnabled() || getRaytracedReflectionEnabled() ? &rtSSR : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd);
|
|
wiRenderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, drawscene_flags);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
wiProfiler::EndRange(range); // Opaque Scene
|
|
}
|
|
|
|
device->BindShadingRateImage(nullptr, cmd);
|
|
});
|
|
|
|
cmd = device->BeginCommandList();
|
|
wiJobSystem::Execute(ctx, [this, cmd](wiJobArgs args) {
|
|
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
wiRenderer::UpdateCameraCB(wiRenderer::GetCamera(), cmd);
|
|
wiRenderer::BindCommonResources(cmd);
|
|
|
|
RenderSSS(cmd);
|
|
|
|
RenderDeferredComposition(cmd);
|
|
|
|
DownsampleDepthBuffer(cmd);
|
|
|
|
RenderLightShafts(cmd);
|
|
|
|
RenderVolumetrics(cmd);
|
|
|
|
RenderSceneMIPChain(cmd);
|
|
|
|
RenderSSR(cmd);
|
|
|
|
RenderTransparents(cmd);
|
|
|
|
RenderPostprocessChain(cmd);
|
|
});
|
|
|
|
RenderPath2D::Render();
|
|
|
|
wiJobSystem::Wait(ctx);
|
|
}
|
|
|
|
void RenderPath3D::Compose(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
wiImageParams fx;
|
|
fx.blendFlag = BLENDMODE_OPAQUE;
|
|
fx.quality = QUALITY_LINEAR;
|
|
fx.enableFullScreen();
|
|
|
|
device->EventBegin("Composition", cmd);
|
|
wiImage::Draw(GetLastPostprocessRT(), fx, cmd);
|
|
device->EventEnd(cmd);
|
|
|
|
if (wiRenderer::GetDebugLightCulling() || wiRenderer::GetVariableRateShadingClassificationDebug())
|
|
{
|
|
wiImage::Draw((Texture*)wiRenderer::GetTexture(TEXTYPE_2D_DEBUGUAV), wiImageParams((float)wiRenderer::GetDevice()->GetScreenWidth(), (float)wiRenderer::GetDevice()->GetScreenHeight()), cmd);
|
|
}
|
|
|
|
RenderPath2D::Compose(cmd);
|
|
}
|
|
|
|
void RenderPath3D::RenderFrameSetUp(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
const wiScene::Scene& scene = wiScene::GetScene();
|
|
|
|
device->BindResource(CS, &depthBuffer_Copy1, TEXSLOT_DEPTH, cmd);
|
|
wiRenderer::UpdateRenderData(visibility_main, cmd);
|
|
|
|
if (getAO() == AO_RTAO || wiRenderer::GetRaytracedShadowsEnabled() || getRaytracedReflectionEnabled())
|
|
{
|
|
wiRenderer::UpdateRaytracingAccelerationStructures(scene, cmd);
|
|
}
|
|
|
|
Viewport viewport;
|
|
viewport.Width = (float)smallDepth.GetDesc().Width;
|
|
viewport.Height = (float)smallDepth.GetDesc().Height;
|
|
device->BindViewports(1, &viewport, cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_occlusionculling, cmd);
|
|
|
|
wiRenderer::OcclusionCulling_Render(visibility_main, cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
}
|
|
void RenderPath3D::RenderReflections(CommandList cmd) const
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("Reflection rendering", cmd);
|
|
|
|
if (visibility_main.planar_reflection_visible)
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
wiRenderer::UpdateCameraCB(wiRenderer::GetRefCamera(), cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)depthBuffer_Reflection.GetDesc().Width;
|
|
vp.Height = (float)depthBuffer_Reflection.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_reflection, cmd);
|
|
|
|
wiRenderer::DrawScene(visibility_reflection, RENDERPASS_TEXTURE, cmd);
|
|
wiRenderer::DrawSky(wiScene::GetScene(), cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
}
|
|
|
|
wiProfiler::EndRange(range); // Reflection Rendering
|
|
}
|
|
|
|
void RenderPath3D::RenderSSS(CommandList cmd) const
|
|
{
|
|
if (getSSSEnabled() && getSSSBlurAmount() > 0)
|
|
{
|
|
wiRenderer::Postprocess_SSS(
|
|
rtLinearDepth,
|
|
GetGbuffer_Read(),
|
|
renderpass_SSS[0],
|
|
renderpass_SSS[1],
|
|
renderpass_SSS[2],
|
|
cmd,
|
|
getSSSBlurAmount()
|
|
);
|
|
}
|
|
}
|
|
void RenderPath3D::RenderDeferredComposition(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
auto range = wiProfiler::BeginRangeGPU("Sky and Composition", cmd);
|
|
|
|
if (wiRenderer::GetRaytracedShadowsEnabled() && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE))
|
|
{
|
|
int output = device->GetFrameCount() % 2;
|
|
int history = 1 - output;
|
|
|
|
wiRenderer::Postprocess_Denoise(
|
|
*GetGbuffer_Read(GBUFFER_LIGHTBUFFER_DIFFUSE),
|
|
rtDiffuseTemporal[history],
|
|
rtDiffuseTemporal[output],
|
|
*GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY),
|
|
rtLinearDepth,
|
|
depthBuffer_Copy1,
|
|
cmd
|
|
);
|
|
wiRenderer::Postprocess_Denoise(
|
|
*GetGbuffer_Read(GBUFFER_LIGHTBUFFER_SPECULAR),
|
|
rtSpecularTemporal[history],
|
|
rtSpecularTemporal[output],
|
|
*GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY),
|
|
rtLinearDepth,
|
|
depthBuffer_Copy1,
|
|
cmd
|
|
);
|
|
}
|
|
|
|
device->RenderPassBegin(&renderpass_deferredcomposition, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)depthBuffer.GetDesc().Width;
|
|
vp.Height = (float)depthBuffer.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DeferredComposition(
|
|
GetGbuffer_Read(),
|
|
depthBuffer_Copy,
|
|
cmd
|
|
);
|
|
|
|
wiRenderer::DrawSky(wiScene::Scene(), cmd);
|
|
|
|
RenderOutline(cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
void RenderPath3D::RenderLinearDepth(CommandList cmd) const
|
|
{
|
|
wiRenderer::Postprocess_Lineardepth(depthBuffer_Copy, rtLinearDepth, cmd);
|
|
}
|
|
void RenderPath3D::RenderAO(CommandList cmd) const
|
|
{
|
|
wiRenderer::GetDevice()->UnbindResources(TEXSLOT_RENDERPATH_AO, 1, cmd);
|
|
|
|
if (getAOEnabled())
|
|
{
|
|
switch (getAO())
|
|
{
|
|
case AO_SSAO:
|
|
wiRenderer::Postprocess_SSAO(
|
|
depthBuffer_Copy,
|
|
rtLinearDepth,
|
|
rtAO,
|
|
cmd,
|
|
getAORange(),
|
|
getAOSampleCount(),
|
|
getAOPower()
|
|
);
|
|
break;
|
|
case AO_HBAO:
|
|
wiRenderer::Postprocess_HBAO(
|
|
rtLinearDepth,
|
|
rtAO,
|
|
cmd,
|
|
getAOPower()
|
|
);
|
|
break;
|
|
case AO_MSAO:
|
|
wiRenderer::Postprocess_MSAO(
|
|
rtLinearDepth,
|
|
rtAO,
|
|
cmd,
|
|
getAOPower()
|
|
);
|
|
break;
|
|
case AO_RTAO:
|
|
wiRenderer::Postprocess_RTAO(
|
|
wiScene::GetScene(),
|
|
depthBuffer_Copy,
|
|
rtLinearDepth,
|
|
depthBuffer_Copy1,
|
|
rtAO,
|
|
cmd,
|
|
getAORange(),
|
|
getAOSampleCount(),
|
|
getAOPower()
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void RenderPath3D::RenderSSR(CommandList cmd) const
|
|
{
|
|
if (getRaytracedReflectionEnabled())
|
|
{
|
|
wiRenderer::Postprocess_RTReflection(
|
|
wiScene::GetScene(),
|
|
depthBuffer_Copy,
|
|
GetGbuffer_Read(),
|
|
rtSSR,
|
|
cmd
|
|
);
|
|
}
|
|
else if (getSSREnabled())
|
|
{
|
|
wiRenderer::Postprocess_SSR(
|
|
rtSceneCopy,
|
|
depthBuffer_Copy,
|
|
rtLinearDepth,
|
|
GetGbuffer_Read(),
|
|
rtSSR,
|
|
cmd
|
|
);
|
|
}
|
|
}
|
|
void RenderPath3D::DownsampleDepthBuffer(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
Viewport viewport;
|
|
viewport.Width = (float)smallDepth.GetDesc().Width;
|
|
viewport.Height = (float)smallDepth.GetDesc().Height;
|
|
device->BindViewports(1, &viewport, cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_downsampledepthbuffer, cmd);
|
|
|
|
wiRenderer::DownsampleDepthBuffer(depthBuffer_Copy, cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
}
|
|
void RenderPath3D::RenderOutline(CommandList cmd) const
|
|
{
|
|
if (getOutlineEnabled())
|
|
{
|
|
wiRenderer::Postprocess_Outline(rtLinearDepth, cmd, getOutlineThreshold(), getOutlineThickness(), getOutlineColor());
|
|
}
|
|
}
|
|
void RenderPath3D::RenderLightShafts(CommandList cmd) const
|
|
{
|
|
XMVECTOR sunDirection = XMLoadFloat3(&wiScene::GetScene().weather.sunDirection);
|
|
if (getLightShaftsEnabled() && XMVectorGetX(XMVector3Dot(sunDirection, wiRenderer::GetCamera().GetAt())) > 0)
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
device->EventBegin("Light Shafts", cmd);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, TEXSLOT_ONDEMAND_COUNT, cmd);
|
|
|
|
// Render sun stencil cutout:
|
|
{
|
|
device->RenderPassBegin(&renderpass_lightshafts, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)depthBuffer.GetDesc().Width;
|
|
vp.Height = (float)depthBuffer.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DrawSun(cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
}
|
|
|
|
// Radial blur on the sun:
|
|
{
|
|
XMVECTOR sunPos = XMVector3Project(sunDirection * 100000, 0, 0,
|
|
1.0f, 1.0f, 0.1f, 1.0f,
|
|
wiRenderer::GetCamera().GetProjection(), wiRenderer::GetCamera().GetView(), XMMatrixIdentity());
|
|
{
|
|
XMFLOAT2 sun;
|
|
XMStoreFloat2(&sun, sunPos);
|
|
wiRenderer::Postprocess_LightShafts(*renderpass_lightshafts.desc.attachments.back().texture, rtSun[1], cmd, sun);
|
|
}
|
|
}
|
|
device->EventEnd(cmd);
|
|
}
|
|
}
|
|
void RenderPath3D::RenderVolumetrics(CommandList cmd) const
|
|
{
|
|
if (getVolumeLightsEnabled() && wiRenderer::IsRequestedVolumetricLightRendering())
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("Volumetric Lights", cmd);
|
|
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
device->RenderPassBegin(&renderpass_volumetriclight, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)rtVolumetricLights[0].GetDesc().Width;
|
|
vp.Height = (float)rtVolumetricLights[0].GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DrawVolumeLights(visibility_main, depthBuffer_Copy, cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
wiRenderer::Postprocess_Blur_Bilateral(
|
|
rtVolumetricLights[0],
|
|
rtLinearDepth,
|
|
rtVolumetricLights[1],
|
|
rtVolumetricLights[0],
|
|
cmd
|
|
);
|
|
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
}
|
|
void RenderPath3D::RenderSceneMIPChain(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
auto range = wiProfiler::BeginRangeGPU("Scene MIP Chain", cmd);
|
|
device->EventBegin("RenderSceneMIPChain", cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_downsamplescene, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)rtSceneCopy.GetDesc().Width;
|
|
vp.Height = (float)rtSceneCopy.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiImageParams fx;
|
|
fx.enableFullScreen();
|
|
fx.sampleFlag = SAMPLEMODE_CLAMP;
|
|
fx.quality = QUALITY_LINEAR;
|
|
wiImage::Draw(GetDeferred_Read(), fx, cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
wiRenderer::MIPGEN_OPTIONS mipopt;
|
|
mipopt.gaussian_temp = &rtSceneCopy_tmp;
|
|
wiRenderer::GenerateMipChain(rtSceneCopy, wiRenderer::MIPGENFILTER_GAUSSIAN, cmd, mipopt);
|
|
|
|
device->EventEnd(cmd);
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
void RenderPath3D::RenderTransparents(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
// Water ripple rendering:
|
|
{
|
|
// todo: refactor water ripples and avoid clear if there is none!
|
|
device->RenderPassBegin(&renderpass_waterripples, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)rtWaterRipple.GetDesc().Width;
|
|
vp.Height = (float)rtWaterRipple.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DrawWaterRipples(cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
}
|
|
|
|
device->UnbindResources(TEXSLOT_GBUFFER0, 1, cmd);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, TEXSLOT_ONDEMAND_COUNT, cmd);
|
|
|
|
device->RenderPassBegin(&renderpass_transparent, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)renderpass_transparent.desc.attachments[0].texture->GetDesc().Width;
|
|
vp.Height = (float)renderpass_transparent.desc.attachments[0].texture->GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
// Transparent scene
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("Transparent Scene", cmd);
|
|
|
|
device->BindResource(PS, &rtLinearDepth, TEXSLOT_LINEARDEPTH, cmd);
|
|
device->BindResource(PS, getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd);
|
|
device->BindResource(PS, &rtSceneCopy, TEXSLOT_RENDERPATH_REFRACTION, cmd);
|
|
device->BindResource(PS, &rtWaterRipple, TEXSLOT_RENDERPATH_WATERRIPPLES, cmd);
|
|
|
|
uint32_t drawscene_flags = 0;
|
|
drawscene_flags |= wiRenderer::DRAWSCENE_TRANSPARENT;
|
|
drawscene_flags |= wiRenderer::DRAWSCENE_OCCLUSIONCULLING;
|
|
drawscene_flags |= wiRenderer::DRAWSCENE_HAIRPARTICLE;
|
|
wiRenderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, drawscene_flags);
|
|
|
|
wiProfiler::EndRange(range); // Transparent Scene
|
|
}
|
|
|
|
wiRenderer::DrawLightVisualizers(visibility_main, cmd);
|
|
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("EmittedParticles - Render", cmd);
|
|
wiRenderer::DrawSoftParticles(visibility_main, rtLinearDepth, false, cmd);
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
|
|
if (getVolumeLightsEnabled() && wiRenderer::IsRequestedVolumetricLightRendering())
|
|
{
|
|
device->EventBegin("Contribute Volumetric Lights", cmd);
|
|
wiRenderer::Postprocess_Upsample_Bilateral(rtVolumetricLights[0], rtLinearDepth,
|
|
*renderpass_transparent.desc.attachments[0].texture, cmd, true, 1.5f);
|
|
device->EventEnd(cmd);
|
|
}
|
|
|
|
if (getLightShaftsEnabled())
|
|
{
|
|
device->EventBegin("Contribute LightShafts", cmd);
|
|
wiImageParams fx;
|
|
fx.enableFullScreen();
|
|
fx.blendFlag = BLENDMODE_ADDITIVE;
|
|
wiImage::Draw(&rtSun[1], fx, cmd);
|
|
device->EventEnd(cmd);
|
|
}
|
|
|
|
if (getLensFlareEnabled())
|
|
{
|
|
wiRenderer::DrawLensFlares(visibility_main, depthBuffer_Copy, cmd);
|
|
}
|
|
|
|
wiRenderer::DrawDebugWorld(wiScene::GetScene(), wiRenderer::GetCamera(), cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
|
|
// Distortion particles:
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("EmittedParticles - Render (Distortion)", cmd);
|
|
device->RenderPassBegin(&renderpass_particledistortion, cmd);
|
|
|
|
Viewport vp;
|
|
vp.Width = (float)rtParticleDistortion.GetDesc().Width;
|
|
vp.Height = (float)rtParticleDistortion.GetDesc().Height;
|
|
device->BindViewports(1, &vp, cmd);
|
|
|
|
wiRenderer::DrawSoftParticles(visibility_main, rtLinearDepth, true, cmd);
|
|
|
|
device->RenderPassEnd(cmd);
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
}
|
|
void RenderPath3D::RenderPostprocessChain(CommandList cmd) const
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
const Texture* rt_first = nullptr; // not ping-ponged with read / write
|
|
const Texture* rt_read = GetDeferred_Read();
|
|
const Texture* rt_write = &rtPostprocess_HDR;
|
|
|
|
// 1.) HDR post process chain
|
|
{
|
|
if (getVolumetricCloudsEnabled())
|
|
{
|
|
const Texture* lightShaftTemp = nullptr;
|
|
|
|
wiRenderer::Postprocess_VolumetricClouds(*rt_read, *rt_write, *lightShaftTemp, rtLinearDepth, depthBuffer_Copy, cmd);
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
if (wiRenderer::GetTemporalAAEnabled() && !wiRenderer::GetTemporalAADebugEnabled())
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
|
|
int output = device->GetFrameCount() % 2;
|
|
int history = 1 - output;
|
|
wiRenderer::Postprocess_TemporalAA(
|
|
*rt_read, rtTemporalAA[history],
|
|
*GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY),
|
|
rtLinearDepth,
|
|
depthBuffer_Copy1,
|
|
rtTemporalAA[output],
|
|
cmd
|
|
);
|
|
rt_first = &rtTemporalAA[output];
|
|
}
|
|
|
|
if (getDepthOfFieldEnabled())
|
|
{
|
|
wiRenderer::Postprocess_DepthOfField(rt_first == nullptr ? *rt_read : *rt_first, *rt_write, rtLinearDepth, cmd, getDepthOfFieldFocus(), getDepthOfFieldStrength(), getDepthOfFieldAspect());
|
|
rt_first = nullptr;
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
if (getMotionBlurEnabled())
|
|
{
|
|
wiRenderer::Postprocess_MotionBlur(rt_first == nullptr ? *rt_read : *rt_first, *GetGbuffer_Read(GBUFFER_NORMAL_VELOCITY), rtLinearDepth, *rt_write, cmd, getMotionBlurStrength());
|
|
rt_first = nullptr;
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
if (getBloomEnabled())
|
|
{
|
|
wiRenderer::Postprocess_Bloom(rt_first == nullptr ? *rt_read : *rt_first, rtBloom, rtBloom_tmp, *rt_write, cmd, getBloomThreshold());
|
|
rt_first = nullptr;
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
}
|
|
|
|
// 2.) Tone mapping HDR -> LDR
|
|
{
|
|
rt_write = &rtPostprocess_LDR[0];
|
|
|
|
wiRenderer::Postprocess_Tonemap(
|
|
*rt_read,
|
|
getEyeAdaptionEnabled() ? *wiRenderer::ComputeLuminance(*GetDeferred_Read(), cmd) : *wiTextureHelper::getColor(wiColor::Gray()),
|
|
getMSAASampleCount() > 1 ? rtParticleDistortion_Resolved : rtParticleDistortion,
|
|
*rt_write,
|
|
cmd,
|
|
getExposure(),
|
|
getDitherEnabled(),
|
|
getColorGradingEnabled() ? (colorGradingTex != nullptr ? colorGradingTex->texture : wiTextureHelper::getColorGradeDefault()) : nullptr
|
|
);
|
|
|
|
rt_read = rt_write;
|
|
rt_write = &rtPostprocess_LDR[1];
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
// 3.) LDR post process chain
|
|
{
|
|
if (getSharpenFilterEnabled())
|
|
{
|
|
wiRenderer::Postprocess_Sharpen(*rt_read, *rt_write, cmd, getSharpenFilterAmount());
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
if (getFXAAEnabled())
|
|
{
|
|
wiRenderer::Postprocess_FXAA(*rt_read, *rt_write, cmd);
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
if (getChromaticAberrationEnabled())
|
|
{
|
|
wiRenderer::Postprocess_Chromatic_Aberration(*rt_read, *rt_write, cmd, getChromaticAberrationAmount());
|
|
|
|
std::swap(rt_read, rt_write);
|
|
device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd);
|
|
}
|
|
|
|
// GUI Background blurring:
|
|
{
|
|
auto range = wiProfiler::BeginRangeGPU("GUI Background Blur", cmd);
|
|
device->EventBegin("GUI Background Blur", cmd);
|
|
wiRenderer::Postprocess_Downsample4x(*rt_read, rtGUIBlurredBackground[0], cmd);
|
|
wiRenderer::Postprocess_Downsample4x(rtGUIBlurredBackground[0], rtGUIBlurredBackground[2], cmd);
|
|
wiRenderer::Postprocess_Blur_Gaussian(rtGUIBlurredBackground[2], rtGUIBlurredBackground[1], rtGUIBlurredBackground[2], cmd, -1,-1, true);
|
|
device->EventEnd(cmd);
|
|
wiProfiler::EndRange(range);
|
|
}
|
|
}
|
|
}
|