Formalize material-driven panoramic skybox path
This commit is contained in:
@@ -1,11 +1,49 @@
|
||||
#include "Components/CameraComponent.h"
|
||||
|
||||
#include "Core/Asset/ResourceManager.h"
|
||||
#include "Resources/Material/Material.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string ToStdString(const Containers::String& value) {
|
||||
return std::string(value.CStr());
|
||||
}
|
||||
|
||||
bool HasVirtualPathScheme(const std::string& path) {
|
||||
return path.find("://") != std::string::npos;
|
||||
}
|
||||
|
||||
std::string EncodeAssetRef(const Resources::AssetRef& assetRef) {
|
||||
if (!assetRef.IsValid()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return ToStdString(assetRef.assetGuid.ToString()) + "," +
|
||||
std::to_string(assetRef.localID) + "," +
|
||||
std::to_string(static_cast<int>(assetRef.resourceType));
|
||||
}
|
||||
|
||||
bool TryDecodeAssetRef(const std::string& value, Resources::AssetRef& outRef) {
|
||||
const size_t firstComma = value.find(',');
|
||||
const size_t secondComma = firstComma == std::string::npos ? std::string::npos : value.find(',', firstComma + 1);
|
||||
if (firstComma == std::string::npos || secondComma == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
outRef.assetGuid = Resources::AssetGUID::ParseOrDefault(Containers::String(value.substr(0, firstComma).c_str()));
|
||||
outRef.localID = static_cast<Resources::LocalID>(std::stoull(value.substr(firstComma + 1, secondComma - firstComma - 1)));
|
||||
outRef.resourceType = static_cast<Resources::ResourceType>(std::stoi(value.substr(secondComma + 1)));
|
||||
return outRef.IsValid();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void CameraComponent::SetFieldOfView(float value) {
|
||||
m_fieldOfView = std::clamp(value, 1.0f, 179.0f);
|
||||
}
|
||||
@@ -35,7 +73,64 @@ void CameraComponent::SetViewportRect(const Math::Rect& value) {
|
||||
m_viewportRect = Math::Rect(x, y, right - x, bottom - y);
|
||||
}
|
||||
|
||||
void CameraComponent::SetSkyboxMaterialPath(const std::string& materialPath) {
|
||||
m_skyboxMaterialPath = materialPath;
|
||||
m_skyboxMaterialRef.Reset();
|
||||
|
||||
if (materialPath.empty()) {
|
||||
m_skyboxMaterial.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
m_skyboxMaterial = Resources::ResourceManager::Get().Load<Resources::Material>(materialPath.c_str());
|
||||
if (!Resources::ResourceManager::Get().TryGetAssetRef(
|
||||
materialPath.c_str(),
|
||||
Resources::ResourceType::Material,
|
||||
m_skyboxMaterialRef)) {
|
||||
m_skyboxMaterialRef.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraComponent::SetSkyboxMaterial(const Resources::ResourceHandle<Resources::Material>& material) {
|
||||
m_skyboxMaterial = material;
|
||||
m_skyboxMaterialPath =
|
||||
material.Get() != nullptr
|
||||
? ToStdString(material->GetPath())
|
||||
: std::string();
|
||||
|
||||
if (m_skyboxMaterialPath.empty() ||
|
||||
!Resources::ResourceManager::Get().TryGetAssetRef(
|
||||
m_skyboxMaterialPath.c_str(),
|
||||
Resources::ResourceType::Material,
|
||||
m_skyboxMaterialRef)) {
|
||||
m_skyboxMaterialRef.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraComponent::SetSkyboxMaterial(Resources::Material* material) {
|
||||
SetSkyboxMaterial(Resources::ResourceHandle<Resources::Material>(material));
|
||||
}
|
||||
|
||||
void CameraComponent::Serialize(std::ostream& os) const {
|
||||
Resources::AssetRef serializedSkyboxMaterialRef = m_skyboxMaterialRef;
|
||||
std::string serializedSkyboxMaterialPath = m_skyboxMaterialPath;
|
||||
if (serializedSkyboxMaterialPath.empty() && m_skyboxMaterial.Get() != nullptr) {
|
||||
serializedSkyboxMaterialPath = ToStdString(m_skyboxMaterial->GetPath());
|
||||
}
|
||||
|
||||
if (!serializedSkyboxMaterialRef.IsValid() &&
|
||||
!serializedSkyboxMaterialPath.empty() &&
|
||||
!HasVirtualPathScheme(serializedSkyboxMaterialPath) &&
|
||||
Resources::ResourceManager::Get().TryGetAssetRef(
|
||||
serializedSkyboxMaterialPath.c_str(),
|
||||
Resources::ResourceType::Material,
|
||||
serializedSkyboxMaterialRef)) {
|
||||
}
|
||||
|
||||
if (serializedSkyboxMaterialRef.IsValid() || !HasVirtualPathScheme(serializedSkyboxMaterialPath)) {
|
||||
serializedSkyboxMaterialPath.clear();
|
||||
}
|
||||
|
||||
os << "projection=" << static_cast<int>(m_projectionType) << ";";
|
||||
os << "fov=" << m_fieldOfView << ";";
|
||||
os << "orthoSize=" << m_orthographicSize << ";";
|
||||
@@ -49,13 +144,21 @@ void CameraComponent::Serialize(std::ostream& os) const {
|
||||
os << "viewportRect=" << m_viewportRect.x << "," << m_viewportRect.y << "," << m_viewportRect.width << "," << m_viewportRect.height << ";";
|
||||
os << "clearColor=" << m_clearColor.r << "," << m_clearColor.g << "," << m_clearColor.b << "," << m_clearColor.a << ";";
|
||||
os << "skyboxEnabled=" << (m_skyboxEnabled ? 1 : 0) << ";";
|
||||
os << "skyboxMaterialPath=" << serializedSkyboxMaterialPath << ";";
|
||||
os << "skyboxMaterialRef=" << EncodeAssetRef(serializedSkyboxMaterialRef) << ";";
|
||||
os << "skyboxTopColor=" << m_skyboxTopColor.r << "," << m_skyboxTopColor.g << "," << m_skyboxTopColor.b << "," << m_skyboxTopColor.a << ";";
|
||||
os << "skyboxHorizonColor=" << m_skyboxHorizonColor.r << "," << m_skyboxHorizonColor.g << "," << m_skyboxHorizonColor.b << "," << m_skyboxHorizonColor.a << ";";
|
||||
os << "skyboxBottomColor=" << m_skyboxBottomColor.r << "," << m_skyboxBottomColor.g << "," << m_skyboxBottomColor.b << "," << m_skyboxBottomColor.a << ";";
|
||||
}
|
||||
|
||||
void CameraComponent::Deserialize(std::istream& is) {
|
||||
m_skyboxMaterial.Reset();
|
||||
m_skyboxMaterialPath.clear();
|
||||
m_skyboxMaterialRef.Reset();
|
||||
|
||||
std::string token;
|
||||
std::string pendingSkyboxMaterialPath;
|
||||
Resources::AssetRef pendingSkyboxMaterialRef;
|
||||
while (std::getline(is, token, ';')) {
|
||||
if (token.empty()) {
|
||||
continue;
|
||||
@@ -101,6 +204,10 @@ void CameraComponent::Deserialize(std::istream& is) {
|
||||
ss >> m_clearColor.r >> m_clearColor.g >> m_clearColor.b >> m_clearColor.a;
|
||||
} else if (key == "skyboxEnabled") {
|
||||
m_skyboxEnabled = (std::stoi(value) != 0);
|
||||
} else if (key == "skyboxMaterialPath") {
|
||||
pendingSkyboxMaterialPath = value;
|
||||
} else if (key == "skyboxMaterialRef") {
|
||||
TryDecodeAssetRef(value, pendingSkyboxMaterialRef);
|
||||
} else if (key == "skyboxTopColor") {
|
||||
std::replace(value.begin(), value.end(), ',', ' ');
|
||||
std::istringstream ss(value);
|
||||
@@ -115,6 +222,28 @@ void CameraComponent::Deserialize(std::istream& is) {
|
||||
ss >> m_skyboxBottomColor.r >> m_skyboxBottomColor.g >> m_skyboxBottomColor.b >> m_skyboxBottomColor.a;
|
||||
}
|
||||
}
|
||||
|
||||
if (pendingSkyboxMaterialRef.IsValid()) {
|
||||
m_skyboxMaterialRef = pendingSkyboxMaterialRef;
|
||||
m_skyboxMaterial = Resources::ResourceManager::Get().Load<Resources::Material>(pendingSkyboxMaterialRef);
|
||||
if (m_skyboxMaterial.Get() != nullptr) {
|
||||
m_skyboxMaterialPath = ToStdString(m_skyboxMaterial->GetPath());
|
||||
} else {
|
||||
Containers::String resolvedPath;
|
||||
if (Resources::ResourceManager::Get().TryResolveAssetPath(pendingSkyboxMaterialRef, resolvedPath)) {
|
||||
SetSkyboxMaterialPath(ToStdString(resolvedPath));
|
||||
m_skyboxMaterialRef = pendingSkyboxMaterialRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_skyboxMaterial.Get() == nullptr && !pendingSkyboxMaterialPath.empty()) {
|
||||
SetSkyboxMaterialPath(pendingSkyboxMaterialPath);
|
||||
}
|
||||
|
||||
if (m_skyboxMaterial.Get() == nullptr && pendingSkyboxMaterialRef.IsValid()) {
|
||||
m_skyboxMaterialRef = pendingSkyboxMaterialRef;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Components
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <XCEngine/RHI/RHIEnums.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
@@ -9,10 +11,22 @@ namespace {
|
||||
|
||||
RHI::Format ToRHITextureFormat(Resources::TextureFormat format) {
|
||||
switch (format) {
|
||||
case Resources::TextureFormat::R8_UNORM:
|
||||
return RHI::Format::R8_UNorm;
|
||||
case Resources::TextureFormat::RG8_UNORM:
|
||||
return RHI::Format::R8G8_UNorm;
|
||||
case Resources::TextureFormat::RGBA8_UNORM:
|
||||
return RHI::Format::R8G8B8A8_UNorm;
|
||||
case Resources::TextureFormat::RGBA8_SRGB:
|
||||
return RHI::Format::R8G8B8A8_SRGB;
|
||||
case Resources::TextureFormat::R16_FLOAT:
|
||||
return RHI::Format::R16_Float;
|
||||
case Resources::TextureFormat::R32_FLOAT:
|
||||
return RHI::Format::R32_Float;
|
||||
case Resources::TextureFormat::RGBA16_FLOAT:
|
||||
return RHI::Format::R16G16B16A16_Float;
|
||||
case Resources::TextureFormat::RGBA32_FLOAT:
|
||||
return RHI::Format::R32G32B32A32_Float;
|
||||
default:
|
||||
return RHI::Format::Unknown;
|
||||
}
|
||||
@@ -34,6 +48,43 @@ RHI::TextureType ToRHITextureType(Resources::TextureType textureType) {
|
||||
}
|
||||
}
|
||||
|
||||
RHI::ResourceViewDimension ToRHITextureViewDimension(Resources::TextureType textureType) {
|
||||
switch (textureType) {
|
||||
case Resources::TextureType::Texture2DArray:
|
||||
return RHI::ResourceViewDimension::Texture2DArray;
|
||||
case Resources::TextureType::Texture3D:
|
||||
return RHI::ResourceViewDimension::Texture3D;
|
||||
case Resources::TextureType::TextureCube:
|
||||
return RHI::ResourceViewDimension::TextureCube;
|
||||
case Resources::TextureType::TextureCubeArray:
|
||||
return RHI::ResourceViewDimension::TextureCubeArray;
|
||||
case Resources::TextureType::Texture2D:
|
||||
default:
|
||||
return RHI::ResourceViewDimension::Texture2D;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetTextureBytesPerPixel(Resources::TextureFormat format) {
|
||||
switch (format) {
|
||||
case Resources::TextureFormat::R8_UNORM:
|
||||
return 1;
|
||||
case Resources::TextureFormat::RG8_UNORM:
|
||||
return 2;
|
||||
case Resources::TextureFormat::RGBA8_UNORM:
|
||||
case Resources::TextureFormat::RGBA8_SRGB:
|
||||
case Resources::TextureFormat::R32_FLOAT:
|
||||
return 4;
|
||||
case Resources::TextureFormat::R16_FLOAT:
|
||||
return 2;
|
||||
case Resources::TextureFormat::RGBA16_FLOAT:
|
||||
return 8;
|
||||
case Resources::TextureFormat::RGBA32_FLOAT:
|
||||
return 16;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownMesh(RenderResourceCache::CachedMesh& cachedMesh) {
|
||||
if (cachedMesh.vertexBufferView != nullptr) {
|
||||
cachedMesh.vertexBufferView->Shutdown();
|
||||
@@ -216,14 +267,19 @@ bool RenderResourceCache::UploadTexture(
|
||||
textureDesc.height = texture->GetHeight();
|
||||
textureDesc.depth = texture->GetDepth();
|
||||
textureDesc.mipLevels = texture->GetMipLevels();
|
||||
textureDesc.arraySize = 1;
|
||||
textureDesc.arraySize = std::max<uint32_t>(texture->GetArraySize(), 1u);
|
||||
textureDesc.format = static_cast<uint32_t>(format);
|
||||
textureDesc.textureType = static_cast<uint32_t>(ToRHITextureType(texture->GetTextureType()));
|
||||
textureDesc.sampleCount = 1;
|
||||
textureDesc.sampleQuality = 0;
|
||||
textureDesc.flags = 0;
|
||||
|
||||
const uint32_t rowPitch = texture->GetWidth() * 4;
|
||||
const uint32_t bytesPerPixel = GetTextureBytesPerPixel(texture->GetFormat());
|
||||
if (bytesPerPixel == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t rowPitch = texture->GetWidth() * bytesPerPixel;
|
||||
cachedTexture.texture = device->CreateTexture(
|
||||
textureDesc,
|
||||
texture->GetPixelData(),
|
||||
@@ -235,7 +291,7 @@ bool RenderResourceCache::UploadTexture(
|
||||
|
||||
RHI::ResourceViewDesc textureViewDesc = {};
|
||||
textureViewDesc.format = static_cast<uint32_t>(format);
|
||||
textureViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
textureViewDesc.dimension = ToRHITextureViewDimension(texture->GetTextureType());
|
||||
textureViewDesc.mipLevel = 0;
|
||||
cachedTexture.shaderResourceView = device->CreateShaderResourceView(cachedTexture.texture, textureViewDesc);
|
||||
if (cachedTexture.shaderResourceView == nullptr) {
|
||||
|
||||
@@ -252,6 +252,12 @@ RenderEnvironmentData BuildEnvironmentData(const CameraRenderRequest& request) {
|
||||
return environment;
|
||||
}
|
||||
|
||||
if (const Resources::Material* skyboxMaterial = request.camera->GetSkyboxMaterial()) {
|
||||
environment.mode = RenderEnvironmentMode::MaterialSkybox;
|
||||
environment.materialSkybox.material = skyboxMaterial;
|
||||
return environment;
|
||||
}
|
||||
|
||||
environment.mode = RenderEnvironmentMode::ProceduralSkybox;
|
||||
environment.skybox.topColor = request.camera->GetSkyboxTopColor();
|
||||
environment.skybox.horizonColor = request.camera->GetSkyboxHorizonColor();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -497,18 +497,26 @@ const Resources::Texture* BuiltinForwardPipeline::ResolveTexture(const Resources
|
||||
return ResolveBuiltinBaseColorTexture(material);
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* BuiltinForwardPipeline::ResolveTextureView(
|
||||
const Resources::Texture* texture) {
|
||||
if (texture == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RenderResourceCache::CachedTexture* cachedTexture = m_resourceCache.GetOrCreateTexture(m_device, texture);
|
||||
if (cachedTexture != nullptr && cachedTexture->shaderResourceView != nullptr) {
|
||||
return cachedTexture->shaderResourceView;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* BuiltinForwardPipeline::ResolveTextureView(
|
||||
const VisibleRenderItem& visibleItem) {
|
||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||
const Resources::Texture* texture = ResolveTexture(material);
|
||||
if (texture != nullptr) {
|
||||
const RenderResourceCache::CachedTexture* cachedTexture = m_resourceCache.GetOrCreateTexture(m_device, texture);
|
||||
if (cachedTexture != nullptr && cachedTexture->shaderResourceView != nullptr) {
|
||||
return cachedTexture->shaderResourceView;
|
||||
}
|
||||
}
|
||||
|
||||
return m_fallbackTextureView;
|
||||
RHI::RHIResourceView* textureView = ResolveTextureView(texture);
|
||||
return textureView != nullptr ? textureView : m_fallbackTextureView;
|
||||
}
|
||||
|
||||
BuiltinForwardPipeline::LightingConstants BuiltinForwardPipeline::BuildLightingConstants(
|
||||
|
||||
Reference in New Issue
Block a user