Formalize material-driven panoramic skybox path

This commit is contained in:
2026-04-06 00:39:08 +08:00
parent 8151be0f45
commit 66a6818b89
18 changed files with 860 additions and 82 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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();

View File

@@ -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(