Files
WickedEngine/WickedEngine/RenderPath3D.cpp
T
Turánszki János e81baa9fef renderer updates (#191)
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
2020-11-23 02:30:10 +01:00

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);
}
}
}