diff --git a/PBR/interface/GLTF_PBR_Renderer.hpp b/PBR/interface/GLTF_PBR_Renderer.hpp index fc32c3dc..a6dfc511 100644 --- a/PBR/interface/GLTF_PBR_Renderer.hpp +++ b/PBR/interface/GLTF_PBR_Renderer.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 Diligent Graphics LLC + * Copyright 2019-2026 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -97,6 +97,35 @@ class GLTF_PBR_Renderer : public PBR_Renderer /// Flag indicating which alpha modes to render ALPHA_MODE_FLAGS AlphaModes = ALPHA_MODE_FLAG_ALL; + enum SURFACE_FLAGS : Uint32 + { + /// Render nothing + SURFACE_FLAG_NONE = 0, + + /// Render non-transmission opaque materials + SURFACE_FLAG_OPAQUE = 1u << 0u, + + /// Render non-transmission alpha-masked materials + SURFACE_FLAG_MASK = 1u << 1u, + + /// Render transmission composite materials + SURFACE_FLAG_TRANSMISSION = 1u << 2u, + + /// Render non-transmission alpha-blended materials + SURFACE_FLAG_BLEND = 1u << 3u, + + /// Render all surface buckets + SURFACE_FLAG_ALL = SURFACE_FLAG_OPAQUE | SURFACE_FLAG_MASK | SURFACE_FLAG_TRANSMISSION | SURFACE_FLAG_BLEND + }; + /// Flag indicating which derived surface buckets to render. + SURFACE_FLAGS SurfaceFlags = SURFACE_FLAG_ALL; + + /// Copied linear HDR scene color texture used by transmission composite. + ITextureView* pTransmissionSceneColorSRV = nullptr; + + /// Optional camera position used to sort transmissive surfaces back-to-front. + const float3* pCameraPosition = nullptr; + DebugViewType DebugView = DebugViewType::None; PSO_FLAGS Flags = PSO_FLAG_DEFAULT; @@ -269,23 +298,36 @@ class GLTF_PBR_Renderer : public PBR_Renderer private: RenderInfo m_RenderParams; + enum RENDER_LIST_ID : size_t + { + RENDER_LIST_OPAQUE = 0, + RENDER_LIST_MASK, + RENDER_LIST_TRANSMISSION, + RENDER_LIST_BLEND, + RENDER_LIST_COUNT + }; + struct PrimitiveRenderInfo { - const GLTF::Primitive& Primitive; - const GLTF::Node& Node; + const GLTF::Primitive* Primitive = nullptr; + const GLTF::Node* Node = nullptr; + float SortDistanceSq = 0; PrimitiveRenderInfo(const GLTF::Primitive& _Primitive, - const GLTF::Node& _Node) noexcept : - Primitive{_Primitive}, - Node{_Node} + const GLTF::Node& _Node, + float _SortDistanceSq = 0) noexcept : + Primitive{&_Primitive}, + Node{&_Node}, + SortDistanceSq{_SortDistanceSq} {} }; - std::array, GLTF::Material::ALPHA_MODE_NUM_MODES> m_RenderLists; + std::array, RENDER_LIST_COUNT> m_RenderLists; PsoCacheAccessor m_PbrPSOCache; PsoCacheAccessor m_WireframePSOCache; }; DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::ALPHA_MODE_FLAGS) +DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::SURFACE_FLAGS) } // namespace Diligent diff --git a/PBR/interface/PBR_Renderer.hpp b/PBR/interface/PBR_Renderer.hpp index d0578a65..5e6902ea 100644 --- a/PBR/interface/PBR_Renderer.hpp +++ b/PBR/interface/PBR_Renderer.hpp @@ -592,9 +592,10 @@ class PBR_Renderer PSO_FLAG_ENABLE_TONE_MAPPING = PSO_FLAG_BIT(35), PSO_FLAG_UNSHADED = PSO_FLAG_BIT(36), PSO_FLAG_COMPUTE_MOTION_VECTORS = PSO_FLAG_BIT(37), - PSO_FLAG_ENABLE_SHADOWS = PSO_FLAG_BIT(38), + PSO_FLAG_ENABLE_SHADOWS = PSO_FLAG_BIT(38), + PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE = PSO_FLAG_BIT(39), - PSO_FLAG_LAST = PSO_FLAG_ENABLE_SHADOWS, + PSO_FLAG_LAST = PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE, PSO_FLAG_FIRST_USER_DEFINED = PSO_FLAG_LAST << 1ull, @@ -782,6 +783,8 @@ class PBR_Renderer ITextureView* pIrradianceCubeSRV, ITextureView* pPrefilteredEnvMapSRV) const; + void SetTransmissionSceneColor(IShaderResourceBinding* pSRB, ITextureView* pSceneColorSRV) const; + void SetOITResources(IShaderResourceBinding* pSRB, const OITResources& OITResources) const; /// Initializes internal renderer parameters. diff --git a/PBR/src/GLTF_PBR_Renderer.cpp b/PBR/src/GLTF_PBR_Renderer.cpp index e3c84351..14318b20 100644 --- a/PBR/src/GLTF_PBR_Renderer.cpp +++ b/PBR/src/GLTF_PBR_Renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 Diligent Graphics LLC + * Copyright 2019-2026 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -565,6 +565,18 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, for (std::vector& List : m_RenderLists) List.clear(); + auto GetTransmissionSortDistanceSq = [&](const GLTF::Primitive& Primitive, const GLTF::Node& Node) // + { + if (RenderParams.pCameraPosition == nullptr) + return 0.f; + + const float4x4 NodeTransform = Transforms.NodeGlobalMatrices[Node.Index] * RenderParams.ModelTransform; + const BoundBox WorldBB = Primitive.BB.Transform(NodeTransform); + const float3 Center = (WorldBB.Min + WorldBB.Max) * 0.5f; + const float3 Delta = Center - *RenderParams.pCameraPosition; + return dot(Delta, Delta); + }; + for (const GLTF::Node* pNode : Scene.LinearNodes) { VERIFY_EXPR(pNode != nullptr); @@ -581,18 +593,54 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if ((RenderParams.AlphaModes & (1u << AlphaMode)) == 0) continue; - m_RenderLists[AlphaMode].emplace_back(primitive, *pNode); + RENDER_LIST_ID RenderListId = RENDER_LIST_OPAQUE; + RenderInfo::SURFACE_FLAGS SurfaceFlag = RenderInfo::SURFACE_FLAG_OPAQUE; + + const bool IsTransmissive = m_Settings.EnableTransmission && + Material.Transmission != nullptr && + Material.Transmission->Factor > 0.f; + if (IsTransmissive) + { + RenderListId = RENDER_LIST_TRANSMISSION; + SurfaceFlag = RenderInfo::SURFACE_FLAG_TRANSMISSION; + } + else if (Material.Attribs.AlphaMode == GLTF::Material::ALPHA_MODE_MASK) + { + RenderListId = RENDER_LIST_MASK; + SurfaceFlag = RenderInfo::SURFACE_FLAG_MASK; + } + else if (Material.Attribs.AlphaMode == GLTF::Material::ALPHA_MODE_BLEND) + { + RenderListId = RENDER_LIST_BLEND; + SurfaceFlag = RenderInfo::SURFACE_FLAG_BLEND; + } + + if ((RenderParams.SurfaceFlags & SurfaceFlag) == 0) + continue; + + m_RenderLists[RenderListId].emplace_back(primitive, *pNode, GetTransmissionSortDistanceSq(primitive, *pNode)); } } + if (RenderParams.pCameraPosition != nullptr) + { + std::vector& TransmissionList = m_RenderLists[RENDER_LIST_TRANSMISSION]; + std::sort(TransmissionList.begin(), TransmissionList.end(), + [](const PrimitiveRenderInfo& LHS, const PrimitiveRenderInfo& RHS) // + { + return LHS.SortDistanceSq > RHS.SortDistanceSq; + }); + } + const Uint32 FirstIndexLocation = GLTFModel.GetFirstIndexLocation(); const Uint32 BaseVertex = GLTFModel.GetBaseVertex(); - const std::array AlphaModes // + const std::array RenderListIds // { - GLTF::Material::ALPHA_MODE_OPAQUE, // Opaque primitives - first - GLTF::Material::ALPHA_MODE_MASK, // Alpha-masked primitives - second - GLTF::Material::ALPHA_MODE_BLEND, // Transparent primitives - last (TODO: depth sorting) + RENDER_LIST_OPAQUE, // Non-transmission opaque primitives - first + RENDER_LIST_MASK, // Non-transmission alpha-masked primitives - second + RENDER_LIST_TRANSMISSION, // Transmission composite primitives - third + RENDER_LIST_BLEND, // Non-transmission alpha-blended primitives - last }; IPipelineState* pCurrPSO = nullptr; @@ -603,14 +651,21 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if (PrevTransforms == nullptr) PrevTransforms = &Transforms; - for (GLTF::Material::ALPHA_MODE AlphaMode : AlphaModes) + for (RENDER_LIST_ID RenderListId : RenderListIds) { - const std::vector& RenderList = m_RenderLists[AlphaMode]; + pCurrPSO = nullptr; + pCurrSRB = nullptr; + pCurrMaterial = nullptr; + + const bool IsTransmissionList = RenderListId == RENDER_LIST_TRANSMISSION; + const std::vector& RenderList = m_RenderLists[RenderListId]; for (const PrimitiveRenderInfo& PrimRI : RenderList) { - const GLTF::Node& Node = PrimRI.Node; - const GLTF::Primitive& primitive = PrimRI.Primitive; + VERIFY_EXPR(PrimRI.Node != nullptr && PrimRI.Primitive != nullptr); + const GLTF::Node& Node = *PrimRI.Node; + const GLTF::Primitive& primitive = *PrimRI.Primitive; const GLTF::Material& material = GLTFModel.Materials[primitive.MaterialId]; + const auto AlphaMode = static_cast(material.Attribs.AlphaMode); const float4x4& NodeGlobalMatrix = Transforms.NodeGlobalMatrices[Node.Index]; const float4x4& PrevNodeGlobalMatrix = PrevTransforms->NodeGlobalMatrices[Node.Index]; @@ -629,7 +684,13 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, PSOFlags |= PSO_FLAG_USE_IBL; } + if (IsTransmissionList && RenderParams.pTransmissionSceneColorSRV != nullptr) + { + PSOFlags |= PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE; + } + PSOFlags &= RenderParams.Flags; + const bool IsTransmissionComposite = (PSOFlags & PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE) != PSO_FLAG_NONE; if (RenderParams.Wireframe) PSOFlags |= PSO_FLAG_UNSHADED; @@ -669,6 +730,10 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if (pCurrSRB != pSRB) { pCurrSRB = pSRB; + if (IsTransmissionComposite) + { + SetTransmissionSceneColor(pSRB, RenderParams.pTransmissionSceneColorSRV); + } pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY); } } @@ -678,6 +743,10 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if (pCurrSRB != pCacheBindings->pSRB) { pCurrSRB = pCacheBindings->pSRB; + if (IsTransmissionComposite) + { + SetTransmissionSceneColor(pCurrSRB, RenderParams.pTransmissionSceneColorSRV); + } pCtx->CommitShaderResources(pCurrSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY); } } diff --git a/PBR/src/PBR_Renderer.cpp b/PBR/src/PBR_Renderer.cpp index 34d9cd1a..80eb61e9 100644 --- a/PBR/src/PBR_Renderer.cpp +++ b/PBR/src/PBR_Renderer.cpp @@ -75,7 +75,7 @@ PBR_Renderer::PSOKey::PSOKey(RenderPassType _Type, LoadingAnimation{_LoadingAnimation}, UserValue{_UserValue} { - static_assert(PSO_FLAG_LAST == Uint64{1} << Uint64{38}, "Please handle the new flag below, if necessary"); + static_assert(PSO_FLAG_LAST == Uint64{1} << Uint64{39}, "Please handle the new flag below, if necessary"); static_assert(static_cast(RenderPassType::Count) == 3, "Please handle the new render pass type below, if necessary"); if (Type == RenderPassType::Shadow) { @@ -210,8 +210,9 @@ std::string PBR_Renderer::GetPSOFlagsString(PSO_FLAGS Flags) case PSO_FLAG_ENABLE_SHEEN: FlagsStr += "SHEEN"; break; case PSO_FLAG_ENABLE_ANISOTROPY: FlagsStr += "ANISOTROPY"; break; case PSO_FLAG_ENABLE_IRIDESCENCE: FlagsStr += "IRIDESCENCE"; break; - case PSO_FLAG_ENABLE_TRANSMISSION: FlagsStr += "TRANSMISSION"; break; - case PSO_FLAG_ENABLE_VOLUME: FlagsStr += "VOLUME"; break; + case PSO_FLAG_ENABLE_TRANSMISSION: FlagsStr += "TRANSMISSION"; break; + case PSO_FLAG_ENABLE_VOLUME: FlagsStr += "VOLUME"; break; + case PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE: FlagsStr += "TRANSMISSION_COMPOSITE"; break; case PSO_FLAG_USE_IBL: FlagsStr += "IBL"; break; case PSO_FLAG_USE_LIGHTS: FlagsStr += "LIGHTS"; break; @@ -229,7 +230,7 @@ std::string PBR_Renderer::GetPSOFlagsString(PSO_FLAGS Flags) FlagsStr += std::to_string(PlatformMisc::GetLSB(Flag)); } } - static_assert(PSO_FLAG_LAST == 1ull << 38ull, "Please update the switch above to handle the new flag"); + static_assert(PSO_FLAG_LAST == 1ull << 39ull, "Please update the switch above to handle the new flag"); return FlagsStr; } @@ -1062,6 +1063,23 @@ void PBR_Renderer::SetOITResources(IShaderResourceBinding* pSRB, const OITResour } } +void PBR_Renderer::SetTransmissionSceneColor(IShaderResourceBinding* pSRB, ITextureView* pSceneColorSRV) const +{ + if (!m_Settings.EnableTransmission || pSceneColorSRV == nullptr) + return; + + if (pSRB == nullptr) + { + UNEXPECTED("SRB must not be null"); + return; + } + + if (ShaderResourceVariableX Var{pSRB, SHADER_TYPE_PIXEL, "g_TransmissionSceneColor"}) + { + Var.Set(pSceneColorSRV, SET_SHADER_RESOURCE_FLAG_ALLOW_OVERWRITE); + } +} + void PBR_Renderer::SetMaterialTexture(IShaderResourceBinding* pSRB, ITextureView* pTexSRV, TEXTURE_ATTRIB_ID TextureId) const { if (m_Settings.ShaderTexturesArrayMode == SHADER_TEXTURE_ARRAY_MODE_NONE) @@ -1258,6 +1276,12 @@ void PBR_Renderer::CreateSignature() } }; + if (m_Settings.EnableTransmission) + { + constexpr WebGPUResourceAttribs WGPUSceneColor{WEB_GPU_BINDING_TYPE_DEFAULT, RESOURCE_DIM_TEX_2D}; + AddTextureAndSampler("g_TransmissionSceneColor", Sam_LinearClamp, "g_LinearClampSampler", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, WGPUSceneColor); + } + if (m_Settings.EnableIBL) { constexpr WebGPUResourceAttribs WGPUCubeMap{WEB_GPU_BINDING_TYPE_DEFAULT, RESOURCE_DIM_TEX_CUBE}; @@ -1474,7 +1498,7 @@ ShaderMacroHelper PBR_Renderer::DefineMacros(const PSOKey& Key) const Macros.Add("LOADING_ANIMATION_TRANSITIONING", static_cast(LoadingAnimationMode::Transitioning)); // clang-format on - static_assert(PSO_FLAG_LAST == PSO_FLAG_BIT(38), "Did you add new PSO Flag? You may need to handle it here."); + static_assert(PSO_FLAG_LAST == PSO_FLAG_BIT(39), "Did you add new PSO Flag? You may need to handle it here."); #define ADD_PSO_FLAG_MACRO(Flag) Macros.Add(#Flag, (PSOFlags & PSO_FLAG_##Flag) != PSO_FLAG_NONE) ADD_PSO_FLAG_MACRO(USE_COLOR_MAP); ADD_PSO_FLAG_MACRO(USE_NORMAL_MAP); @@ -1506,6 +1530,7 @@ ShaderMacroHelper PBR_Renderer::DefineMacros(const PSOKey& Key) const ADD_PSO_FLAG_MACRO(ENABLE_IRIDESCENCE); ADD_PSO_FLAG_MACRO(ENABLE_TRANSMISSION); ADD_PSO_FLAG_MACRO(ENABLE_VOLUME); + ADD_PSO_FLAG_MACRO(ENABLE_TRANSMISSION_COMPOSITE); ADD_PSO_FLAG_MACRO(USE_IBL); @@ -1930,8 +1955,9 @@ void PBR_Renderer::CreatePSO(PsoHashMapType& PsoHashMap, Macros.Add("USE_GL_POINT_SIZE", "1"); } + const bool IsTransmissionComposite = (PSOFlags & PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE) != PSO_FLAG_NONE; const Uint32 OITLayerCount = (Key.GetType() == RenderPassType::OITLayers) || - (Key.GetType() == RenderPassType::Main && Key.GetAlphaMode() == ALPHA_MODE_BLEND) ? + (Key.GetType() == RenderPassType::Main && Key.GetAlphaMode() == ALPHA_MODE_BLEND && !IsTransmissionComposite) ? m_Settings.OITLayerCount : 0; Macros.Add("NUM_OIT_LAYERS", static_cast(OITLayerCount)); @@ -2063,6 +2089,11 @@ void PBR_Renderer::CreatePSO(PsoHashMapType& PsoHashMap, else { RenderTargetBlendDesc& RT0 = PSOCreateInfo.GraphicsPipeline.BlendDesc.RenderTargets[0]; + if (IsTransmissionComposite) + { + GraphicsPipeline.DepthStencilDesc.DepthWriteEnable = False; + } + if (AlphaMode == ALPHA_MODE_OPAQUE || AlphaMode == ALPHA_MODE_MASK) { @@ -2189,7 +2220,7 @@ IPipelineState* PBR_Renderer::GetPSO(PsoHashMapType& PsoHashMap, } if (!m_Settings.EnableTransmission) { - Flags &= ~PSO_FLAG_ENABLE_TRANSMISSION; + Flags &= ~(PSO_FLAG_ENABLE_TRANSMISSION | PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE); } if (!m_Settings.EnableVolume) { @@ -2230,7 +2261,7 @@ IPipelineState* PBR_Renderer::GetPSO(PsoHashMapType& PsoHashMap, } if ((Flags & PSO_FLAG_ENABLE_TRANSMISSION) == 0) { - Flags &= ~PSO_FLAG_USE_TRANSMISSION_MAP; + Flags &= ~(PSO_FLAG_USE_TRANSMISSION_MAP | PSO_FLAG_ENABLE_TRANSMISSION_COMPOSITE); } if ((Flags & PSO_FLAG_ENABLE_VOLUME) == 0) { diff --git a/Shaders/PBR/private/RenderPBR.psh b/Shaders/PBR/private/RenderPBR.psh index 6487fcf7..d09068fc 100644 --- a/Shaders/PBR/private/RenderPBR.psh +++ b/Shaders/PBR/private/RenderPBR.psh @@ -40,8 +40,16 @@ # define ALLOW_DEBUG_VIEW 0 #endif +#ifndef ENABLE_TRANSMISSION_COMPOSITE +# define ENABLE_TRANSMISSION_COMPOSITE 0 +#endif + #include "PBR_Textures.fxh" +#if ENABLE_TRANSMISSION_COMPOSITE +Texture2D g_TransmissionSceneColor; +#endif + cbuffer cbFrameAttribs { PBRFrameAttribs g_Frame; @@ -457,8 +465,14 @@ PSOutput main(in VSOutput VSOut, # endif PBRMaterialBasicAttribs BasicAttribs = g_Material.Basic; + float CoverageAlpha = BaseColor.a; + if (BasicAttribs.AlphaMode == PBR_ALPHA_MODE_OPAQUE) + { + CoverageAlpha = 1.0; + } + # if PBR_ALPHA_MODE == PBR_ALPHA_MODE_MASK - if (BaseColor.a < BasicAttribs.AlphaMaskCutoff) + if (CoverageAlpha < BasicAttribs.AlphaMaskCutoff) { discard; } @@ -512,19 +526,31 @@ PSOutput main(in VSOutput VSOut, # endif OutColor.rgb = ResolveLighting(Shading, SrfLighting); -# if ENABLE_TRANSMISSION - { - OutColor.a = 1.0 - Shading.Transmission; - } -# else +# if ENABLE_TRANSMISSION && ENABLE_TRANSMISSION_COMPOSITE { - OutColor.a = BaseColor.a; + uint TransmissionSceneColorWidth; + uint TransmissionSceneColorHeight; + uint TransmissionSceneColorMipCount; + g_TransmissionSceneColor.GetDimensions(0, TransmissionSceneColorWidth, TransmissionSceneColorHeight, TransmissionSceneColorMipCount); + + float2 ScreenUV = VSOut.ClipPos.xy * g_Frame.Camera.f4ViewportSize.zw; + float MaxMip = float(TransmissionSceneColorMipCount > 0u ? TransmissionSceneColorMipCount - 1u : 0u); + float LOD = saturate(Shading.BaseLayer.Srf.PerceptualRoughness) * MaxMip; + float3 Transmitted = g_TransmissionSceneColor.SampleLevel(g_LinearClampSampler, ScreenUV, LOD).rgb * BaseColor.rgb; + + float IOR = max(g_Material.Transmission.IOR, 1.0); + float F0 = (IOR - 1.0) / (IOR + 1.0); + F0 *= F0; + float Fresnel = SchlickReflection(Shading.BaseLayer.NdotV, F0, 1.0); + + OutColor.rgb += Transmitted * Shading.Transmission * (1.0 - Fresnel); } # endif + OutColor.a = CoverageAlpha; } else { - OutColor = BaseColor; + OutColor = float4(BaseColor.rgb, CoverageAlpha); } #if ENABLE_TONE_MAPPING @@ -544,9 +570,9 @@ PSOutput main(in VSOutput VSOut, float Transmittance = 1.0; if (BasicAttribs.AlphaMode == PBR_ALPHA_MODE_BLEND) { - OutColor.rgb *= BaseColor.a; + OutColor.rgb *= CoverageAlpha; #if NUM_OIT_LAYERS > 0 - if (BaseColor.a > OIT_OPACITY_THRESHOLD) + if (CoverageAlpha > OIT_OPACITY_THRESHOLD) { float D = VSOut.ClipPos.z; if (g_Frame.Camera.fNearPlaneDepth > g_Frame.Camera.fFarPlaneDepth) @@ -630,11 +656,7 @@ PSOutput main(in VSOutput VSOut, #endif OutColor.rgb *= Transmittance; - if (BasicAttribs.AlphaMode != PBR_ALPHA_MODE_BLEND) - { - // Write 1.0 alpha to indicate full opacity - OutColor.a = 1.0; - } + OutColor.a = CoverageAlpha; #if CONVERT_OUTPUT_TO_SRGB { diff --git a/Shaders/PBR/public/PBR_Structures.fxh b/Shaders/PBR/public/PBR_Structures.fxh index dd2319dd..6d0e44f0 100644 --- a/Shaders/PBR/public/PBR_Structures.fxh +++ b/Shaders/PBR/public/PBR_Structures.fxh @@ -218,7 +218,7 @@ struct PBRMaterialIridescenceAttribs struct PBRMaterialTransmissionAttribs { float Factor; - float Padding0; + float IOR; float Padding1; float Padding2; };