diff --git a/Hydrogent/interface/HnLight.hpp b/Hydrogent/interface/HnLight.hpp index 6b7a7308..2e78e5e3 100644 --- a/Hydrogent/interface/HnLight.hpp +++ b/Hydrogent/interface/HnLight.hpp @@ -45,6 +45,8 @@ struct PBRShadowMapInfo; namespace USD { +class HnRenderDelegate; + /// Light implementation in Hydrogent. class HnLight final : public pxr::HdLight { @@ -85,11 +87,14 @@ class HnLight final : public pxr::HdLight bool IsShadowMapDirty() const { return m_IsShadowMapDirty; } void SetShadowMapDirty(bool IsDirty) { m_IsShadowMapDirty = IsDirty; } + void PrepareGPUResources(HnRenderDelegate& RenderDelegate); + private: HnLight(const pxr::SdfPath& Id, const pxr::TfToken& TypeId); bool ApproximateAreaLight(pxr::HdSceneDelegate& SceneDelegate, float MetersPerUnit); void ComputeDirectLightProjMatrix(pxr::HdSceneDelegate& SceneDelegate); + void PrecomputeIBLCubemaps(HnRenderDelegate& RenderDelegate); private: const pxr::TfToken m_TypeId; @@ -105,6 +110,9 @@ class HnLight final : public pxr::HdLight float4x4 m_ViewProjMatrix; BoundBox m_SceneBounds; + std::string m_TexturePath; + std::string m_PrecomputedEnvMapPath; + Int32 m_FrameAttribsIndex = 0; Uint32 m_ShadowMapResolution = 1024; RefCntAutoPtr m_ShadowMapSuballocation; diff --git a/Hydrogent/interface/HnRenderDelegate.hpp b/Hydrogent/interface/HnRenderDelegate.hpp index e518f55a..d22a67de 100644 --- a/Hydrogent/interface/HnRenderDelegate.hpp +++ b/Hydrogent/interface/HnRenderDelegate.hpp @@ -394,6 +394,7 @@ class HnRenderDelegate final : public pxr::HdRenderDelegate Uint32 m_MeshResourcesVersion = ~0u; Uint32 m_MaterialResourcesVersion = ~0u; Uint32 m_ShadowAtlasVersion = ~0u; + Uint32 m_LightResourcesVersion = ~0u; }; } // namespace USD diff --git a/Hydrogent/src/HnLight.cpp b/Hydrogent/src/HnLight.cpp index 11aaf976..0340084e 100644 --- a/Hydrogent/src/HnLight.cpp +++ b/Hydrogent/src/HnLight.cpp @@ -29,8 +29,10 @@ #include "HnRenderDelegate.hpp" #include "HnShadowMapManager.hpp" #include "HnTokens.hpp" +#include "HnTextureUtils.hpp" #include +#include #include "pxr/imaging/hd/sceneDelegate.h" @@ -353,6 +355,20 @@ bool HnLight::ApproximateAreaLight(pxr::HdSceneDelegate& SceneDelegate, float Me return ParamsDirty; } +static pxr::SdfAssetPath GetTextureFile(pxr::HdSceneDelegate& SceneDelegate, const pxr::SdfPath& Id) +{ + pxr::SdfAssetPath FilePath; + + const pxr::VtValue TextureFileVal = SceneDelegate.GetLightParamValue(Id, pxr::HdLightTokens->textureFile); + LOG_INFO_MESSAGE("TextureFileVal type: ", TextureFileVal.GetTypeName()); + if (TextureFileVal.IsHolding()) + { + FilePath = TextureFileVal.Get(); + } + + return FilePath; +} + void HnLight::ComputeDirectLightProjMatrix(pxr::HdSceneDelegate& SceneDelegate) { pxr::HdRenderIndex& RenderIndex = SceneDelegate.GetRenderIndex(); @@ -501,6 +517,10 @@ void HnLight::Sync(pxr::HdSceneDelegate* SceneDelegate, LightDirty = true; } } + else if (m_TypeId == pxr::HdPrimTypeTokens->domeLight) + { + m_TexturePath = GetTextureFile(*SceneDelegate, Id).GetAssetPath(); + } else { LOG_ERROR_MESSAGE("Unsupported light type: ", m_TypeId); @@ -603,6 +623,57 @@ void HnLight::Sync(pxr::HdSceneDelegate* SceneDelegate, *DirtyBits = HdLight::Clean; } +void HnLight::PrecomputeIBLCubemaps(HnRenderDelegate& RenderDelegate) +{ + VERIFY_EXPR(m_TypeId == pxr::HdPrimTypeTokens->domeLight && m_TexturePath != m_PrecomputedEnvMapPath); + + RefCntAutoPtr pEnvMap; + if (!m_TexturePath.empty()) + { + TextureLoadInfo LoadInfo; + LoadInfo.Name = m_TexturePath.c_str(); + if (RefCntAutoPtr pLoader = CreateTextureLoaderFromSdfPath(m_TexturePath.c_str(), LoadInfo)) + { + pLoader->CreateTexture(RenderDelegate.GetDevice(), &pEnvMap); + } + } + + if (!pEnvMap) + { + // Create uniform white environment map + TextureDesc EnvMapDesc; + EnvMapDesc.Name = "Default Env Map"; + EnvMapDesc.Type = RESOURCE_DIM_TEX_2D; + EnvMapDesc.Format = TEX_FORMAT_RGBA32_FLOAT; + EnvMapDesc.Width = 32; + EnvMapDesc.Height = 32; + EnvMapDesc.BindFlags = BIND_SHADER_RESOURCE; + EnvMapDesc.MipLevels = 1; + EnvMapDesc.Usage = USAGE_IMMUTABLE; + + std::vector EnvMapData(EnvMapDesc.Width * EnvMapDesc.Height, float4{1}); + TextureSubResData Mip0Data{EnvMapData.data(), EnvMapDesc.Width * sizeof(float4)}; + TextureData InitData = {&Mip0Data, 1}; + + RenderDelegate.GetDevice()->CreateTexture(EnvMapDesc, &InitData, &pEnvMap); + } + + RenderDelegate.GetUSDRenderer()->PrecomputeCubemaps(RenderDelegate.GetDeviceContext(), pEnvMap->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + + m_PrecomputedEnvMapPath = m_TexturePath; +} + +void HnLight::PrepareGPUResources(HnRenderDelegate& RenderDelegate) +{ + if (m_TypeId == pxr::HdPrimTypeTokens->domeLight) + { + if (m_TexturePath != m_PrecomputedEnvMapPath) + { + PrecomputeIBLCubemaps(RenderDelegate); + } + } +} + } // namespace USD } // namespace Diligent diff --git a/Hydrogent/src/HnRenderDelegate.cpp b/Hydrogent/src/HnRenderDelegate.cpp index d8e4f490..e842d988 100644 --- a/Hydrogent/src/HnRenderDelegate.cpp +++ b/Hydrogent/src/HnRenderDelegate.cpp @@ -76,6 +76,7 @@ const pxr::TfTokenVector HnRenderDelegate::SupportedSPrimTypes = { pxr::HdPrimTypeTokens->distantLight, pxr::HdPrimTypeTokens->rectLight, pxr::HdPrimTypeTokens->sphereLight, + pxr::HdPrimTypeTokens->domeLight, }; const pxr::TfTokenVector HnRenderDelegate::SupportedBPrimTypes = { @@ -406,7 +407,8 @@ pxr::HdSprim* HnRenderDelegate::CreateSprim(const pxr::TfToken& TypeId, TypeId == pxr::HdPrimTypeTokens->diskLight || TypeId == pxr::HdPrimTypeTokens->distantLight || TypeId == pxr::HdPrimTypeTokens->rectLight || - TypeId == pxr::HdPrimTypeTokens->sphereLight) + TypeId == pxr::HdPrimTypeTokens->sphereLight || + TypeId == pxr::HdPrimTypeTokens->domeLight) { HnLight* Light = HnLight::Create(SPrimId, TypeId); { @@ -440,7 +442,8 @@ pxr::HdSprim* HnRenderDelegate::CreateFallbackSprim(const pxr::TfToken& TypeId) TypeId == pxr::HdPrimTypeTokens->diskLight || TypeId == pxr::HdPrimTypeTokens->distantLight || TypeId == pxr::HdPrimTypeTokens->rectLight || - TypeId == pxr::HdPrimTypeTokens->sphereLight) + TypeId == pxr::HdPrimTypeTokens->sphereLight || + TypeId == pxr::HdPrimTypeTokens->domeLight) { SPrim = nullptr; } @@ -588,6 +591,19 @@ void HnRenderDelegate::CommitResources(pxr::HdChangeTracker* tracker) } } + { + const auto LightVersion = m_RenderParam->GetAttribVersion(HnRenderParam::GlobalAttrib::Light); + if (m_LightResourcesVersion != LightVersion) + { + std::lock_guard Guard{m_LightsMtx}; + for (auto* pLight : m_Lights) + { + pLight->PrepareGPUResources(*this); + } + m_LightResourcesVersion = LightVersion; + } + } + { GLTF::ResourceManager::TransitionResourceStatesInfo TRSInfo; TRSInfo.VertexBuffers.NewState = RESOURCE_STATE_VERTEX_BUFFER; diff --git a/Hydrogent/src/HnTextureUtils.cpp b/Hydrogent/src/HnTextureUtils.cpp index 00c1f181..e2628d46 100644 --- a/Hydrogent/src/HnTextureUtils.cpp +++ b/Hydrogent/src/HnTextureUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2023 Diligent Graphics LLC + * Copyright 2023-2024 Diligent Graphics LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,9 +38,13 @@ namespace USD RefCntAutoPtr CreateTextureLoaderFromSdfPath(const char* SdfPath, const TextureLoadInfo& LoadInfo) { + pxr::ArResolver& Resolver = pxr::ArGetResolver(); - pxr::ArResolvedPath ResolvedPath{SdfPath}; - std::shared_ptr Asset = pxr::ArGetResolver().OpenAsset(ResolvedPath); + pxr::ArResolvedPath ResolvedPath = Resolver.Resolve(SdfPath); + if (ResolvedPath.empty()) + return {}; + + std::shared_ptr Asset = Resolver.OpenAsset(ResolvedPath); if (!Asset) return {}; diff --git a/PBR/src/PBR_Renderer.cpp b/PBR/src/PBR_Renderer.cpp index c4264d80..cced4714 100644 --- a/PBR/src/PBR_Renderer.cpp +++ b/PBR/src/PBR_Renderer.cpp @@ -659,6 +659,9 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, DrawAttribs drawAttrs(4, DRAW_FLAG_VERIFY_ALL); pCtx->Draw(drawAttrs); } + // Release reference to the environment map + m_pPrecomputeIrradianceCubeSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(nullptr); + pCtx->SetPipelineState(pPrefilterEnvMapPSO); m_pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap); @@ -691,6 +694,9 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, pCtx->Draw(drawAttrs); } } + // Release reference to the environment map + m_pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(nullptr); + // clang-format off StateTransitionDesc Barriers[] =