Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PBR: Fixed noise in IBL irradiance cube map (close #200) #203

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions PBR/src/PBR_Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,12 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
float Roughness;
float EnvMapWidth;
float EnvMapHeight;
uint NumSamples;
float EnvMapMipCount;

uint NumSamples;
uint Padding0;
uint Padding1;
uint Padding2;
};

if (!m_PrecomputeEnvMapAttribsCB)
Expand Down Expand Up @@ -687,10 +692,11 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
VERIFY_EXPR(mip == 0);
{
MapHelper<PrecomputeEnvMapAttribs> Attribs{pCtx, m_PrecomputeEnvMapAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD};
Attribs->Rotation = Matrices[face];
Attribs->EnvMapWidth = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Width);
Attribs->EnvMapHeight = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Height);
Attribs->NumSamples = NumDiffuseSamples;
Attribs->Rotation = Matrices[face];
Attribs->EnvMapWidth = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Width);
Attribs->EnvMapHeight = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Height);
Attribs->EnvMapMipCount = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().MipLevels);
Attribs->NumSamples = NumDiffuseSamples;
}
DrawAttribs drawAttrs(4, DRAW_FLAG_VERIFY_ALL);
pCtx->Draw(drawAttrs);
Expand All @@ -706,11 +712,12 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
ProcessCubemapFaces(pCtx, pPrefilteredEnvMap, [&](ITextureView* pRTV, Uint32 mip, Uint32 face) {
{
MapHelper<PrecomputeEnvMapAttribs> Attribs{pCtx, m_PrecomputeEnvMapAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD};
Attribs->Rotation = Matrices[face];
Attribs->Roughness = static_cast<float>(mip) / static_cast<float>(pPrefilteredEnvMap->GetDesc().MipLevels - 1);
Attribs->EnvMapWidth = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Width);
Attribs->EnvMapHeight = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Height);
Attribs->NumSamples = NumSpecularSamples;
Attribs->Rotation = Matrices[face];
Attribs->Roughness = static_cast<float>(mip) / static_cast<float>(pPrefilteredEnvMap->GetDesc().MipLevels - 1);
Attribs->EnvMapWidth = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Width);
Attribs->EnvMapHeight = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().Height);
Attribs->EnvMapMipCount = static_cast<float>(pEnvironmentMap->GetTexture()->GetDesc().MipLevels);
Attribs->NumSamples = NumSpecularSamples;
}

DrawAttribs drawAttrs(4, DRAW_FLAG_VERIFY_ALL);
Expand Down
22 changes: 13 additions & 9 deletions Shaders/PBR/private/ComputeIrradianceMap.psh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ cbuffer FilterAttribs
float g_Roughness;
float g_EnvMapWidth;
float g_EnvMapHeight;
float g_EnvMipCount;

uint g_NumSamples;
uint _Padding0;
uint _Padding1;
uint _Padding2;
}

float3 SampleEnvrionmentMap(float3 R, float MipLevel)
Expand All @@ -47,7 +52,7 @@ float3 IrradianceMap(float3 N)
// Importance sample the hemisphere with a cosine-weighted distribution
float3 L = ImportanceSampleGGX(Xi, 1.0, N);

#if OPTIMIZE_SAMPLES
#if OPTIMIZE_SAMPLES
// NdotL is equal to cos(theta)
float NoL = max(dot(N, L), 0.0);

Expand All @@ -57,18 +62,17 @@ 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 / NumPixels;

// Applying mip bias produces better results, especially for environments maps with
float OmegaP = ComputeCubeMapPixelSolidAngle(g_EnvMapWidth, g_EnvMapHeight);
#else
// Solid angle of 1 pixel on sphere
float OmegaP = ComputeSphereMapPixelSolidAngle(g_EnvMapWidth, g_EnvMapHeight, acos(L.y), 0.5);
#endif
// Applying mip bias produces better results, especially for environment maps with
// very bright spots.
float MipBias = 1.0;
float MipLevel = max(0.5 * log2(OmegaS / OmegaP) + MipBias, 0.0);
float MipLevel = clamp(0.5 * log2(OmegaS / max(OmegaP, 1e-10)) + MipBias, 0.0, g_EnvMipCount - 1.0);
#else
float MipLevel = 0.0;
#endif
Expand Down
12 changes: 12 additions & 0 deletions Shaders/PBR/private/PBR_PrecomputeCommon.fxh
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@ float3 ImportanceSampleGGX(float2 Xi, float PerceptualRoughness, float3 N)
return TangentX * H.x + TangentY * H.y + N * H.z;
}

float ComputeCubeMapPixelSolidAngle(float Width, float Height)
{
return 4.0 * PI / (6.0 * Width * Height);
}

float ComputeSphereMapPixelSolidAngle(float Width, float Height, float Theta, float Gamma)
{
float dTheta = PI / Width;
float dPhi = 2.0 * PI / Height;
return dPhi * (cos(Theta - 0.5 * dTheta * Gamma) - cos(Theta + 0.5 * dTheta * Gamma));
}

#endif // _PBR_PRECOMPUTE_COMMON_FXH_
21 changes: 13 additions & 8 deletions Shaders/PBR/private/PrefilterEnvMap.psh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ cbuffer FilterAttribs
float g_Roughness;
float g_EnvMapWidth;
float g_EnvMapHeight;
float g_EnvMipCount;

uint g_NumSamples;
uint _Padding0;
uint _Padding1;
uint _Padding2;
}

float3 SampleEnvrionmentMap(float3 R, float MipLevel)
Expand Down Expand Up @@ -71,17 +76,17 @@ float3 PrefilterEnvMap( float PerceptualRoughness, float3 R )
// 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 / NumPixels;
// Applying mip bias produces better results, especially for environments maps with
float OmegaP = ComputeCubeMapPixelSolidAngle(g_EnvMapWidth, g_EnvMapHeight);
#else
// Solid angle of 1 pixel on sphere
float OmegaP = ComputeSphereMapPixelSolidAngle(g_EnvMapWidth, g_EnvMapHeight, acos(L.y), 1.0);
#endif
// Applying mip bias produces better results, especially for environment maps with
// very bright spots.
float MipBias = 1.0;
float MipLevel = (AlphaRoughness == 0.0) ? 0.0 : max(0.5 * log2(OmegaS / OmegaP) + MipBias, 0.0);
float MipBias = 1.0;
float MipLevel = (AlphaRoughness == 0.0) ? 0.0 : clamp(0.5 * log2(OmegaS / max(OmegaP, 1e-10)) + MipBias, 0.0, g_EnvMipCount - 1.0);
#else
float MipLevel = 0.0;
#endif
Expand Down
Loading