diff --git a/Components/interface/EnvMapRenderer.hpp b/Components/interface/EnvMapRenderer.hpp index 3bc941c8..8534443c 100644 --- a/Components/interface/EnvMapRenderer.hpp +++ b/Components/interface/EnvMapRenderer.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h" #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h" @@ -83,16 +84,22 @@ class EnvMapRenderer struct PSOKey { - const int ToneMappingMode; - const bool ConvertOutputToSRGB; - const bool ComputeMotionVectors; - const bool SamplingSphere; + enum ENV_MAP_TYPE : Uint8 + { + ENV_MAP_TYPE_CUBE = 0, + ENV_MAP_TYPE_SPHERE, + ENV_MAP_TYPE_COUNT + }; + const int ToneMappingMode; + const bool ConvertOutputToSRGB; + const bool ComputeMotionVectors; + const ENV_MAP_TYPE EnvMapType; - PSOKey(int _ToneMappingMode, bool _ConvertOutputToSRGB, bool _ComputeMotionVectors, bool _SamplingSphere) : + PSOKey(int _ToneMappingMode, bool _ConvertOutputToSRGB, bool _ComputeMotionVectors, ENV_MAP_TYPE _EnvMapType) : ToneMappingMode{_ToneMappingMode}, ConvertOutputToSRGB{_ConvertOutputToSRGB}, ComputeMotionVectors{_ComputeMotionVectors}, - SamplingSphere{_SamplingSphere} + EnvMapType{_EnvMapType} {} constexpr bool operator==(const PSOKey& rhs) const @@ -100,14 +107,14 @@ class EnvMapRenderer return (ToneMappingMode == rhs.ToneMappingMode && ConvertOutputToSRGB == rhs.ConvertOutputToSRGB && ComputeMotionVectors == rhs.ComputeMotionVectors && - SamplingSphere == rhs.SamplingSphere); + EnvMapType == rhs.EnvMapType); } struct Hasher { size_t operator()(const PSOKey& Key) const { - return ComputeHash(Key.ToneMappingMode, Key.ConvertOutputToSRGB, Key.ComputeMotionVectors, Key.SamplingSphere); + return ComputeHash(Key.ToneMappingMode, Key.ConvertOutputToSRGB, Key.ComputeMotionVectors, Key.EnvMapType); } }; }; @@ -125,10 +132,17 @@ class EnvMapRenderer std::unordered_map, PSOKey::Hasher> m_PSOs; - IPipelineState* m_pCurrentPSO = nullptr; + struct Resources + { + RefCntAutoPtr SRB; + IShaderResourceVariable* pEnvMapVar = nullptr; + + explicit operator bool() const { return SRB; } + }; + std::array m_Resources; - RefCntAutoPtr m_SRB; - IShaderResourceVariable* m_pEnvMapVar = nullptr; + IPipelineState* m_pCurrentPSO = nullptr; + IShaderResourceBinding* m_pCurrentSRB = nullptr; struct EnvMapShaderAttribs; std::unique_ptr m_ShaderAttribs; diff --git a/Components/src/EnvMapRenderer.cpp b/Components/src/EnvMapRenderer.cpp index 70109b30..206fb11a 100644 --- a/Components/src/EnvMapRenderer.cpp +++ b/Components/src/EnvMapRenderer.cpp @@ -121,7 +121,9 @@ IPipelineState* EnvMapRenderer::GetPSO(const PSOKey& Key) .Add("CONVERT_OUTPUT_TO_SRGB", Key.ConvertOutputToSRGB) .Add("TONE_MAPPING_MODE", Key.ToneMappingMode) .Add("COMPUTE_MOTION_VECTORS", Key.ComputeMotionVectors) - .Add("SAMPLING_SPHERE", Key.SamplingSphere); + .Add("ENV_MAP_TYPE_CUBE", static_cast(PSOKey::ENV_MAP_TYPE_CUBE)) + .Add("ENV_MAP_TYPE_SPHERE", static_cast(PSOKey::ENV_MAP_TYPE_SPHERE)) + .Add("ENV_MAP_TYPE", static_cast(Key.EnvMapType)); ShaderCI.Macros = Macros; RefCntAutoPtr pVS; @@ -180,11 +182,12 @@ IPipelineState* EnvMapRenderer::GetPSO(const PSOKey& Key) PSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "cbCameraAttribs")->Set(m_pCameraAttribsCB); PSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "cbEnvMapRenderAttribs")->Set(m_RenderAttribsCB); - if (!m_SRB) + auto& Res = m_Resources[Key.EnvMapType]; + if (!Res) { - PSO->CreateShaderResourceBinding(&m_SRB, true); - m_pEnvMapVar = m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "EnvMap"); - VERIFY_EXPR(m_pEnvMapVar != nullptr); + PSO->CreateShaderResourceBinding(&Res.SRB, true); + Res.pEnvMapVar = Res.SRB->GetVariableByName(SHADER_TYPE_PIXEL, "EnvMap"); + VERIFY_EXPR(Res.pEnvMapVar != nullptr); } m_PSOs.emplace(Key, PSO); @@ -201,15 +204,20 @@ void EnvMapRenderer::Prepare(IDeviceContext* pContext, return; } + const PSOKey::ENV_MAP_TYPE EnvMapType = Attribs.pEnvMap->GetTexture()->GetDesc().IsCube() ? + PSOKey::ENV_MAP_TYPE_CUBE : + PSOKey::ENV_MAP_TYPE_SPHERE; - m_pCurrentPSO = GetPSO({ToneMapping.iToneMappingMode, Attribs.ConvertOutputToSRGB, Attribs.ComputeMotionVectors, !Attribs.pEnvMap->GetTexture()->GetDesc().IsCube()}); + m_pCurrentPSO = GetPSO({ToneMapping.iToneMappingMode, Attribs.ConvertOutputToSRGB, Attribs.ComputeMotionVectors, EnvMapType}); if (m_pCurrentPSO == nullptr) { UNEXPECTED("Failed to get PSO"); return; } - m_pEnvMapVar->Set(Attribs.pEnvMap); + m_Resources[EnvMapType].pEnvMapVar->Set(Attribs.pEnvMap); + m_pCurrentSRB = m_Resources[EnvMapType].SRB; + VERIFY_EXPR(m_pCurrentSRB != nullptr); if (m_ShaderAttribs) { @@ -253,7 +261,7 @@ void EnvMapRenderer::Render(IDeviceContext* pContext) } pContext->SetPipelineState(m_pCurrentPSO); - pContext->CommitShaderResources(m_SRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + pContext->CommitShaderResources(m_pCurrentSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY); DrawAttribs drawAttribs{3, DRAW_FLAG_VERIFY_ALL}; pContext->Draw(drawAttribs); } diff --git a/PBR/interface/PBR_Renderer.hpp b/PBR/interface/PBR_Renderer.hpp index 8d067493..63e4fde4 100644 --- a/PBR/interface/PBR_Renderer.hpp +++ b/PBR/interface/PBR_Renderer.hpp @@ -681,28 +681,51 @@ class PBR_Renderer { IBL_FEATURE_FLAG_NONE = 0, IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES = 1u << 0u, - IBL_FEATURE_FLAG_SAMPLING_SPHERE = 1u << 1u }; + DECLARE_FRIEND_FLAG_ENUM_OPERATORS(IBL_FEATURE_FLAGS) struct IBL_PSOKey { + enum PSO_TYPE : Uint8 + { + PSO_TYPE_IRRADIANCE_CUBE = 0, + PSO_TYPE_PREFILTERED_ENV_MAP, + }; + enum ENV_MAP_TYPE : Uint8 + { + ENV_MAP_TYPE_CUBE = 0, + ENV_MAP_TYPE_SPHERE, + ENV_MAP_TYPE_NUM_TYPES + }; + + const PSO_TYPE PSOType; + const ENV_MAP_TYPE EnvMapType; const IBL_FEATURE_FLAGS FeatureFlags; const TEXTURE_FORMAT RTVFormat; - IBL_PSOKey(IBL_FEATURE_FLAGS _FeatureFlags, TEXTURE_FORMAT Format) : - FeatureFlags{_FeatureFlags}, RTVFormat{Format} + IBL_PSOKey(PSO_TYPE _PSOType, + ENV_MAP_TYPE _EnvMapType, + IBL_FEATURE_FLAGS _FeatureFlags, + TEXTURE_FORMAT _Format) : + PSOType{_PSOType}, + EnvMapType{_EnvMapType}, + FeatureFlags{_FeatureFlags}, + RTVFormat{_Format} {} constexpr bool operator==(const IBL_PSOKey& rhs) const { - return FeatureFlags == rhs.FeatureFlags && RTVFormat == rhs.RTVFormat; + return (PSOType == rhs.PSOType && + EnvMapType == rhs.EnvMapType && + FeatureFlags == rhs.FeatureFlags && + RTVFormat == rhs.RTVFormat); } struct Hasher { size_t operator()(const IBL_PSOKey& Key) const { - return ComputeHash(Key.FeatureFlags, Key.RTVFormat); + return ComputeHash(Key.PSOType, Key.EnvMapType, Key.FeatureFlags, Key.RTVFormat); } }; }; @@ -733,8 +756,8 @@ class PBR_Renderer RefCntAutoPtr m_pIrradianceCubeSRV; RefCntAutoPtr m_pPrefilteredEnvMapSRV; - RefCntAutoPtr m_pPrecomputeIrradianceCubeSRB; - RefCntAutoPtr m_pPrefilterEnvMapSRB; + std::array, IBL_PSOKey::ENV_MAP_TYPE_NUM_TYPES> m_pPrecomputeIrradianceCubeSRB; + std::array, IBL_PSOKey::ENV_MAP_TYPE_NUM_TYPES> m_pPrefilterEnvMapSRB; IBL_PipelineStateObjectCache m_IBL_PSOCache; @@ -750,7 +773,7 @@ class PBR_Renderer }; DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS) - +DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::IBL_FEATURE_FLAGS) inline constexpr PBR_Renderer::PSO_FLAGS PBR_Renderer::GetTextureAttribPSOFlag(PBR_Renderer::TEXTURE_ATTRIB_ID AttribId) { diff --git a/PBR/src/PBR_Renderer.cpp b/PBR/src/PBR_Renderer.cpp index 0a7378db..92985b8d 100644 --- a/PBR/src/PBR_Renderer.cpp +++ b/PBR/src/PBR_Renderer.cpp @@ -493,18 +493,22 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, IBL_FEATURE_FLAGS FeatureFlags = IBL_FEATURE_FLAG_NONE; if (OptimizeSamples) - FeatureFlags = static_cast(FeatureFlags | IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES); + FeatureFlags |= IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES; - if (!pEnvironmentMap->GetTexture()->GetDesc().IsCube()) - FeatureFlags = static_cast(FeatureFlags | IBL_FEATURE_FLAG_SAMPLING_SPHERE); + const IBL_PSOKey::ENV_MAP_TYPE EnvMapType = pEnvironmentMap->GetTexture()->GetDesc().IsCube() ? + IBL_PSOKey::ENV_MAP_TYPE_CUBE : + IBL_PSOKey::ENV_MAP_TYPE_SPHERE; - auto& pPrecomputeIrradianceCubePSO = m_IBL_PSOCache[IBL_PSOKey{FeatureFlags, m_pIrradianceCubeSRV->GetDesc().Format}]; + ShaderMacroHelper Macros; + Macros + .Add("OPTIMIZE_SAMPLES", (FeatureFlags & IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES) != 0) + .Add("ENV_MAP_TYPE_CUBE", static_cast(IBL_PSOKey::ENV_MAP_TYPE_CUBE)) + .Add("ENV_MAP_TYPE_SPHERE", static_cast(IBL_PSOKey::ENV_MAP_TYPE_SPHERE)) + .Add("ENV_MAP_TYPE", static_cast(EnvMapType)); + + auto& pPrecomputeIrradianceCubePSO = m_IBL_PSOCache[IBL_PSOKey{IBL_PSOKey::PSO_TYPE_IRRADIANCE_CUBE, EnvMapType, FeatureFlags, m_pIrradianceCubeSRV->GetDesc().Format}]; if (!pPrecomputeIrradianceCubePSO) { - ShaderMacroHelper Macros; - Macros.AddShaderMacro("OPTIMIZE_SAMPLES", (FeatureFlags & IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES) != 0); - Macros.AddShaderMacro("SAMPLING_SPHERE", (FeatureFlags & IBL_FEATURE_FLAG_SAMPLING_SPHERE) != 0); - ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; ShaderCI.pShaderSourceStreamFactory = &DiligentFXShaderSourceStreamFactory::GetInstance(); @@ -557,16 +561,13 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, pPrecomputeIrradianceCubePSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "FilterAttribs")->Set(m_PrecomputeEnvMapAttribsCB); } - if (!m_pPrecomputeIrradianceCubeSRB) - pPrecomputeIrradianceCubePSO->CreateShaderResourceBinding(&m_pPrecomputeIrradianceCubeSRB, true); + auto& pPrecomputeIrradianceCubeSRB = m_pPrecomputeIrradianceCubeSRB[EnvMapType]; + if (!pPrecomputeIrradianceCubeSRB) + pPrecomputeIrradianceCubePSO->CreateShaderResourceBinding(&pPrecomputeIrradianceCubeSRB, true); - auto& pPrefilterEnvMapPSO = m_IBL_PSOCache[IBL_PSOKey{FeatureFlags, m_pPrefilteredEnvMapSRV->GetDesc().Format}]; + auto& pPrefilterEnvMapPSO = m_IBL_PSOCache[IBL_PSOKey{IBL_PSOKey::PSO_TYPE_PREFILTERED_ENV_MAP, EnvMapType, FeatureFlags, m_pPrefilteredEnvMapSRV->GetDesc().Format}]; if (!pPrefilterEnvMapPSO) { - ShaderMacroHelper Macros; - Macros.AddShaderMacro("OPTIMIZE_SAMPLES", (FeatureFlags & IBL_FEATURE_FLAG_OPTIMIZE_SAMPLES) != 0); - Macros.AddShaderMacro("SAMPLING_SPHERE", (FeatureFlags & IBL_FEATURE_FLAG_SAMPLING_SPHERE) != 0); - ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; ShaderCI.pShaderSourceStreamFactory = &DiligentFXShaderSourceStreamFactory::GetInstance(); @@ -619,8 +620,9 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, pPrefilterEnvMapPSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "FilterAttribs")->Set(m_PrecomputeEnvMapAttribsCB); } - if (!m_pPrefilterEnvMapSRB) - pPrefilterEnvMapPSO->CreateShaderResourceBinding(&m_pPrefilterEnvMapSRB, true); + auto& pPrefilterEnvMapSRB = m_pPrefilterEnvMapSRB[EnvMapType]; + if (!pPrefilterEnvMapSRB) + pPrefilterEnvMapPSO->CreateShaderResourceBinding(&pPrefilterEnvMapSRB, true); // clang-format off const std::array Matrices = @@ -635,8 +637,8 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, // clang-format on pCtx->SetPipelineState(pPrecomputeIrradianceCubePSO); - m_pPrecomputeIrradianceCubeSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap); - pCtx->CommitShaderResources(m_pPrecomputeIrradianceCubeSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pPrecomputeIrradianceCubeSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap); + pCtx->CommitShaderResources(pPrecomputeIrradianceCubeSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); auto* pIrradianceCube = m_pIrradianceCubeSRV->GetTexture(); for (Uint32 face = 0; face < 6; ++face) @@ -661,8 +663,8 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, } pCtx->SetPipelineState(pPrefilterEnvMapPSO); - m_pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap); - pCtx->CommitShaderResources(m_pPrefilterEnvMapSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap); + pCtx->CommitShaderResources(pPrefilterEnvMapSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); auto* pPrefilteredEnvMap = m_pPrefilteredEnvMapSRV->GetTexture(); const auto& PrefilteredEnvMapDesc = pPrefilteredEnvMap->GetDesc(); for (Uint32 mip = 0; mip < PrefilteredEnvMapDesc.MipLevels; ++mip) diff --git a/Shaders/Common/private/EnvMap.psh b/Shaders/Common/private/EnvMap.psh index 579678dd..7f1bc646 100644 --- a/Shaders/Common/private/EnvMap.psh +++ b/Shaders/Common/private/EnvMap.psh @@ -1,7 +1,6 @@ #include "BasicStructures.fxh" #include "ToneMapping.fxh" #include "ShaderUtilities.fxh" -#include "PBR_PrecomputeCommon.fxh" cbuffer cbCameraAttribs { @@ -19,19 +18,19 @@ cbuffer cbEnvMapRenderAttribs float Unusued2; } -#if SAMPLING_SPHERE -Texture2D EnvMap; -#else +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE TextureCube EnvMap; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE +Texture2D EnvMap; #endif SamplerState EnvMap_sampler; float3 SampleEnvrionmentMap(float3 R, float MipLevel) { -#if SAMPLING_SPHERE - return EnvMap.SampleLevel(EnvMap_sampler, TransformDirectionToSpherePoint(R), MipLevel).rgb; -#else +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE return EnvMap.SampleLevel(EnvMap_sampler, R, MipLevel).rgb; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE + return EnvMap.SampleLevel(EnvMap_sampler, TransformDirectionToSphereMapUV(R), MipLevel).rgb; #endif } diff --git a/Shaders/Common/public/ShaderUtilities.fxh b/Shaders/Common/public/ShaderUtilities.fxh index 6f7aff24..c4cccef0 100644 --- a/Shaders/Common/public/ShaderUtilities.fxh +++ b/Shaders/Common/public/ShaderUtilities.fxh @@ -84,4 +84,10 @@ float2 GetMotionVector(float2 ClipPos, float2 PrevClipPos) return ClipPos - PrevClipPos; } +float2 TransformDirectionToSphereMapUV(float3 Direction) +{ + float OneOverPi = 0.3183098862; + return OneOverPi * float2(0.5 * atan2(Direction.z, Direction.x), asin(Direction.y)) + float2(0.5, 0.5); +} + #endif //_SHADER_UTILITIES_FXH_ diff --git a/Shaders/PBR/private/ComputeIrradianceMap.psh b/Shaders/PBR/private/ComputeIrradianceMap.psh index d5c5c8e7..9d9ba162 100644 --- a/Shaders/PBR/private/ComputeIrradianceMap.psh +++ b/Shaders/PBR/private/ComputeIrradianceMap.psh @@ -1,16 +1,18 @@ // Generates an irradiance cube from an environment map using convolution #include "PBR_PrecomputeCommon.fxh" +#include "ShaderUtilities.fxh" #ifndef OPTIMIZE_SAMPLES # define OPTIMIZE_SAMPLES 1 #endif -#if SAMPLING_SPHERE -Texture2D g_EnvironmentMap; -#else +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE TextureCube g_EnvironmentMap; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE +Texture2D g_EnvironmentMap; #endif + SamplerState g_EnvironmentMap_sampler; cbuffer FilterAttribs @@ -25,10 +27,10 @@ cbuffer FilterAttribs float3 SampleEnvrionmentMap(float3 R, float MipLevel) { -#if SAMPLING_SPHERE - return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, TransformDirectionToSpherePoint(R), MipLevel).rgb; -#else +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, R, MipLevel).rgb; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE + return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, TransformDirectionToSphereMapUV(R), MipLevel).rgb; #endif } @@ -55,8 +57,13 @@ float3 IrradianceMap(float3 N) // Solid angle of current smple float OmegaS = 1.0 / (float(g_NumSamples) * pdf); + float NumPixels = g_EnvMapWidth * g_EnvMapHeight; +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE + NumPixels *= 6.0; +#endif + // Solid angle of 1 pixel across all cube faces - float OmegaP = 4.0 * PI / (6.0 * g_EnvMapWidth * g_EnvMapHeight); + float OmegaP = 4.0 * PI / NumPixels; // Applying mip bias produces better results, especially for environments maps with // very bright spots. diff --git a/Shaders/PBR/private/PBR_PrecomputeCommon.fxh b/Shaders/PBR/private/PBR_PrecomputeCommon.fxh index 61672508..ed5b37c7 100644 --- a/Shaders/PBR/private/PBR_PrecomputeCommon.fxh +++ b/Shaders/PBR/private/PBR_PrecomputeCommon.fxh @@ -39,9 +39,4 @@ float3 ImportanceSampleGGX(float2 Xi, float PerceptualRoughness, float3 N) return TangentX * H.x + TangentY * H.y + N * H.z; } -float2 TransformDirectionToSpherePoint(float3 Direction) -{ - return rcp(PI) * float2(0.5 * atan2(Direction.z, Direction.x), asin(Direction.y)) + float2(0.5, 0.5); -} - #endif // _PBR_PRECOMPUTE_COMMON_FXH_ diff --git a/Shaders/PBR/private/PrefilterEnvMap.psh b/Shaders/PBR/private/PrefilterEnvMap.psh index 713647c9..8db59af4 100644 --- a/Shaders/PBR/private/PrefilterEnvMap.psh +++ b/Shaders/PBR/private/PrefilterEnvMap.psh @@ -1,13 +1,14 @@ #include "PBR_PrecomputeCommon.fxh" +#include "ShaderUtilities.fxh" #ifndef OPTIMIZE_SAMPLES # define OPTIMIZE_SAMPLES 1 #endif -#if SAMPLING_SPHERE -Texture2D g_EnvironmentMap; -#else -TextureCube g_EnvironmentMap; +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE +TextureCube g_EnvironmentMap; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE +Texture2D g_EnvironmentMap; #endif SamplerState g_EnvironmentMap_sampler; @@ -23,10 +24,10 @@ cbuffer FilterAttribs float3 SampleEnvrionmentMap(float3 R, float MipLevel) { -#if SAMPLING_SPHERE - return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, TransformDirectionToSpherePoint(R), MipLevel).rgb; -#else +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, R, MipLevel).rgb; +#elif ENV_MAP_TYPE == ENV_MAP_TYPE_SPHERE + return g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, TransformDirectionToSphereMapUV(R), MipLevel).rgb; #endif } @@ -66,10 +67,17 @@ float3 PrefilterEnvMap( float PerceptualRoughness, float3 R ) // Probability Distribution Function float AlphaRoughness = PerceptualRoughness * PerceptualRoughness; float pdf = max(SmithGGXSampleDirectionPDF(V, N, L, AlphaRoughness), 0.0001); + // Solid angle of current smple float OmegaS = 1.0 / (float(g_NumSamples) * pdf); + + float NumPixels = g_EnvMapWidth * g_EnvMapHeight; +#if ENV_MAP_TYPE == ENV_MAP_TYPE_CUBE + NumPixels *= 6.0; +#endif + // Solid angle of 1 pixel across all cube faces - float OmegaP = 4.0 * PI / (6.0 * g_EnvMapWidth * g_EnvMapHeight); + float OmegaP = 4.0 * PI / NumPixels; // Applying mip bias produces better results, especially for environments maps with // very bright spots. float MipBias = 1.0;