Formalize material-driven panoramic skybox path
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "Rendering/RenderSurface.h"
|
||||
#include "Resources/BuiltinResources.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
|
||||
@@ -234,6 +235,11 @@ bool BuiltinForwardPipeline::HasProceduralSkybox(const RenderSceneData& sceneDat
|
||||
sceneData.cameraData.perspectiveProjection;
|
||||
}
|
||||
|
||||
bool BuiltinForwardPipeline::HasSkybox(const RenderSceneData& sceneData) const {
|
||||
return sceneData.environment.HasSkybox() &&
|
||||
sceneData.cameraData.perspectiveProjection;
|
||||
}
|
||||
|
||||
bool BuiltinForwardPipeline::BeginForwardScenePass(const RenderPassContext& passContext) {
|
||||
const RenderContext& context = passContext.renderContext;
|
||||
const RenderSurface& surface = passContext.surface;
|
||||
@@ -290,7 +296,7 @@ bool BuiltinForwardPipeline::BeginForwardScenePass(const RenderPassContext& pass
|
||||
: sceneData.cameraData.clearColor;
|
||||
const float clearValues[4] = { clearColor.r, clearColor.g, clearColor.b, clearColor.a };
|
||||
if (HasRenderClearFlag(sceneData.cameraData.clearFlags, RenderClearFlags::Color) &&
|
||||
!HasProceduralSkybox(sceneData)) {
|
||||
!HasSkybox(sceneData)) {
|
||||
for (RHI::RHIResourceView* renderTarget : renderTargets) {
|
||||
if (renderTarget != nullptr) {
|
||||
commandList->ClearRenderTarget(renderTarget, clearValues, 1, clearRects);
|
||||
@@ -351,7 +357,7 @@ bool BuiltinForwardPipeline::ExecuteForwardSkyboxPass(const RenderPassContext& p
|
||||
const RenderSurface& surface = passContext.surface;
|
||||
const RenderSceneData& sceneData = passContext.sceneData;
|
||||
|
||||
if (!HasProceduralSkybox(sceneData)) {
|
||||
if (!HasSkybox(sceneData)) {
|
||||
return true;
|
||||
}
|
||||
if (surface.GetDepthAttachment() == nullptr) {
|
||||
@@ -361,7 +367,10 @@ bool BuiltinForwardPipeline::ExecuteForwardSkyboxPass(const RenderPassContext& p
|
||||
if (!EnsureSkyboxResources(context) ||
|
||||
m_skyboxPipelineLayout == nullptr ||
|
||||
m_skyboxPipelineState == nullptr ||
|
||||
m_skyboxConstantSet == nullptr) {
|
||||
m_skyboxEnvironmentSet.set == nullptr ||
|
||||
m_skyboxMaterialSet.set == nullptr ||
|
||||
m_skyboxTextureSet.set == nullptr ||
|
||||
m_skyboxSamplerSet.set == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinForwardPipeline skybox pass failed to initialize runtime skybox resources");
|
||||
@@ -380,13 +389,46 @@ bool BuiltinForwardPipeline::ExecuteForwardSkyboxPass(const RenderPassContext& p
|
||||
sceneData.cameraData.aspectRatio);
|
||||
constants.cameraForwardAndUnused = Math::Vector4(sceneData.cameraData.worldForward, 0.0f);
|
||||
|
||||
m_skyboxConstantSet->WriteConstant(0, &constants, sizeof(constants));
|
||||
const Resources::Material* skyboxMaterial = sceneData.environment.HasMaterialSkybox()
|
||||
? sceneData.environment.materialSkybox.material
|
||||
: nullptr;
|
||||
const Resources::Texture* skyboxTexture = ResolveSkyboxTexture(skyboxMaterial);
|
||||
RHI::RHIResourceView* skyboxTextureView = ResolveTextureView(skyboxTexture);
|
||||
const bool useTexturedSkybox = sceneData.environment.HasMaterialSkybox() && skyboxTextureView != nullptr;
|
||||
if (skyboxTextureView == nullptr) {
|
||||
skyboxTextureView = m_fallbackTextureView;
|
||||
}
|
||||
|
||||
const BuiltinSkyboxMaterialData skyboxMaterialData = BuildBuiltinSkyboxMaterialData(skyboxMaterial);
|
||||
SkyboxMaterialConstants materialConstants = {};
|
||||
materialConstants.tintAndExposure = Math::Vector4(
|
||||
skyboxMaterialData.tint.x,
|
||||
skyboxMaterialData.tint.y,
|
||||
skyboxMaterialData.tint.z,
|
||||
std::max(0.0f, skyboxMaterialData.exposure));
|
||||
materialConstants.rotationRadiansAndMode = Math::Vector4(
|
||||
Math::Radians(skyboxMaterialData.rotationDegrees),
|
||||
useTexturedSkybox ? 1.0f : 0.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
|
||||
m_skyboxEnvironmentSet.set->WriteConstant(0, &constants, sizeof(constants));
|
||||
m_skyboxMaterialSet.set->WriteConstant(0, &materialConstants, sizeof(materialConstants));
|
||||
if (m_skyboxBoundTextureView != skyboxTextureView) {
|
||||
m_skyboxTextureSet.set->Update(0, skyboxTextureView);
|
||||
m_skyboxBoundTextureView = skyboxTextureView;
|
||||
}
|
||||
|
||||
RHI::RHICommandList* commandList = context.commandList;
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
commandList->SetPipelineState(m_skyboxPipelineState);
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = { m_skyboxConstantSet };
|
||||
commandList->SetGraphicsDescriptorSets(0, 1, descriptorSets, m_skyboxPipelineLayout);
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = {
|
||||
m_skyboxEnvironmentSet.set,
|
||||
m_skyboxMaterialSet.set,
|
||||
m_skyboxTextureSet.set,
|
||||
m_skyboxSamplerSet.set
|
||||
};
|
||||
commandList->SetGraphicsDescriptorSets(0, 4, descriptorSets, m_skyboxPipelineLayout);
|
||||
commandList->Draw(3, 1, 0, 0);
|
||||
return true;
|
||||
}
|
||||
@@ -543,8 +585,10 @@ bool BuiltinForwardPipeline::CreatePipelineResources(const RenderContext& contex
|
||||
bool BuiltinForwardPipeline::EnsureSkyboxResources(const RenderContext& context) {
|
||||
if (m_skyboxPipelineLayout != nullptr &&
|
||||
m_skyboxPipelineState != nullptr &&
|
||||
m_skyboxConstantPool != nullptr &&
|
||||
m_skyboxConstantSet != nullptr) {
|
||||
m_skyboxEnvironmentSet.set != nullptr &&
|
||||
m_skyboxMaterialSet.set != nullptr &&
|
||||
m_skyboxTextureSet.set != nullptr &&
|
||||
m_skyboxSamplerSet.set != nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -570,19 +614,52 @@ bool BuiltinForwardPipeline::CreateSkyboxResources(const RenderContext& context)
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::DescriptorSetLayoutBinding constantBinding = {};
|
||||
constantBinding.binding = 0;
|
||||
constantBinding.type = static_cast<uint32_t>(RHI::DescriptorType::CBV);
|
||||
constantBinding.count = 1;
|
||||
constantBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
RHI::DescriptorSetLayoutBinding environmentBinding = {};
|
||||
environmentBinding.binding = 0;
|
||||
environmentBinding.type = static_cast<uint32_t>(RHI::DescriptorType::CBV);
|
||||
environmentBinding.count = 1;
|
||||
environmentBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
|
||||
RHI::DescriptorSetLayoutDesc constantLayout = {};
|
||||
constantLayout.bindings = &constantBinding;
|
||||
constantLayout.bindingCount = 1;
|
||||
RHI::DescriptorSetLayoutBinding materialBinding = environmentBinding;
|
||||
|
||||
RHI::DescriptorSetLayoutBinding textureBinding = {};
|
||||
textureBinding.binding = 0;
|
||||
textureBinding.type = static_cast<uint32_t>(RHI::DescriptorType::SRV);
|
||||
textureBinding.count = 1;
|
||||
textureBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
|
||||
RHI::DescriptorSetLayoutBinding samplerBinding = {};
|
||||
samplerBinding.binding = 0;
|
||||
samplerBinding.type = static_cast<uint32_t>(RHI::DescriptorType::Sampler);
|
||||
samplerBinding.count = 1;
|
||||
samplerBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
|
||||
RHI::DescriptorSetLayoutDesc environmentLayout = {};
|
||||
environmentLayout.bindings = &environmentBinding;
|
||||
environmentLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc materialLayout = {};
|
||||
materialLayout.bindings = &materialBinding;
|
||||
materialLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc textureLayout = {};
|
||||
textureLayout.bindings = &textureBinding;
|
||||
textureLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc samplerLayout = {};
|
||||
samplerLayout.bindings = &samplerBinding;
|
||||
samplerLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc setLayouts[] = {
|
||||
environmentLayout,
|
||||
materialLayout,
|
||||
textureLayout,
|
||||
samplerLayout
|
||||
};
|
||||
|
||||
RHI::RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
||||
pipelineLayoutDesc.setLayouts = &constantLayout;
|
||||
pipelineLayoutDesc.setLayoutCount = 1;
|
||||
pipelineLayoutDesc.setLayouts = setLayouts;
|
||||
pipelineLayoutDesc.setLayoutCount = 4;
|
||||
m_skyboxPipelineLayout = m_device->CreatePipelineLayout(pipelineLayoutDesc);
|
||||
if (m_skyboxPipelineLayout == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
@@ -592,27 +669,54 @@ bool BuiltinForwardPipeline::CreateSkyboxResources(const RenderContext& context)
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::DescriptorPoolDesc constantPoolDesc = {};
|
||||
constantPoolDesc.type = RHI::DescriptorHeapType::CBV_SRV_UAV;
|
||||
constantPoolDesc.descriptorCount = 1;
|
||||
constantPoolDesc.shaderVisible = false;
|
||||
m_skyboxConstantPool = m_device->CreateDescriptorPool(constantPoolDesc);
|
||||
if (m_skyboxConstantPool == nullptr) {
|
||||
auto createSkyboxDescriptorSet =
|
||||
[this](const RHI::DescriptorSetLayoutDesc& layout,
|
||||
RHI::DescriptorHeapType heapType,
|
||||
bool shaderVisible,
|
||||
OwnedDescriptorSet& ownedSet) -> bool {
|
||||
RHI::DescriptorPoolDesc poolDesc = {};
|
||||
poolDesc.type = heapType;
|
||||
poolDesc.descriptorCount = 1;
|
||||
poolDesc.shaderVisible = shaderVisible;
|
||||
ownedSet.pool = m_device->CreateDescriptorPool(poolDesc);
|
||||
if (ownedSet.pool == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ownedSet.set = ownedSet.pool->AllocateSet(layout);
|
||||
return ownedSet.set != nullptr;
|
||||
};
|
||||
|
||||
if (!createSkyboxDescriptorSet(
|
||||
environmentLayout,
|
||||
RHI::DescriptorHeapType::CBV_SRV_UAV,
|
||||
false,
|
||||
m_skyboxEnvironmentSet) ||
|
||||
!createSkyboxDescriptorSet(
|
||||
materialLayout,
|
||||
RHI::DescriptorHeapType::CBV_SRV_UAV,
|
||||
false,
|
||||
m_skyboxMaterialSet) ||
|
||||
!createSkyboxDescriptorSet(
|
||||
textureLayout,
|
||||
RHI::DescriptorHeapType::CBV_SRV_UAV,
|
||||
true,
|
||||
m_skyboxTextureSet) ||
|
||||
!createSkyboxDescriptorSet(
|
||||
samplerLayout,
|
||||
RHI::DescriptorHeapType::Sampler,
|
||||
true,
|
||||
m_skyboxSamplerSet)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinForwardPipeline failed to create skybox descriptor pool");
|
||||
"BuiltinForwardPipeline failed to allocate skybox descriptor sets");
|
||||
DestroySkyboxResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_skyboxConstantSet = m_skyboxConstantPool->AllocateSet(constantLayout);
|
||||
if (m_skyboxConstantSet == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinForwardPipeline failed to allocate skybox descriptor set");
|
||||
DestroySkyboxResources();
|
||||
return false;
|
||||
}
|
||||
m_skyboxSamplerSet.set->UpdateSampler(0, m_sampler);
|
||||
m_skyboxTextureSet.set->Update(0, m_fallbackTextureView);
|
||||
m_skyboxBoundTextureView = m_fallbackTextureView;
|
||||
|
||||
m_skyboxPipelineState = m_device->CreatePipelineState(
|
||||
CreateSkyboxPipelineDesc(
|
||||
@@ -638,17 +742,11 @@ void BuiltinForwardPipeline::DestroySkyboxResources() {
|
||||
m_skyboxPipelineState = nullptr;
|
||||
}
|
||||
|
||||
if (m_skyboxConstantSet != nullptr) {
|
||||
m_skyboxConstantSet->Shutdown();
|
||||
delete m_skyboxConstantSet;
|
||||
m_skyboxConstantSet = nullptr;
|
||||
}
|
||||
|
||||
if (m_skyboxConstantPool != nullptr) {
|
||||
m_skyboxConstantPool->Shutdown();
|
||||
delete m_skyboxConstantPool;
|
||||
m_skyboxConstantPool = nullptr;
|
||||
}
|
||||
DestroyOwnedDescriptorSet(m_skyboxSamplerSet);
|
||||
DestroyOwnedDescriptorSet(m_skyboxTextureSet);
|
||||
DestroyOwnedDescriptorSet(m_skyboxMaterialSet);
|
||||
DestroyOwnedDescriptorSet(m_skyboxEnvironmentSet);
|
||||
m_skyboxBoundTextureView = nullptr;
|
||||
|
||||
if (m_skyboxPipelineLayout != nullptr) {
|
||||
m_skyboxPipelineLayout->Shutdown();
|
||||
|
||||
Reference in New Issue
Block a user