Skip to content

Commit

Permalink
Added loading HDR equirectangular texture (close #189)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikhailGorobets committed May 7, 2024
1 parent 80160fc commit 2bfba45
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 22 deletions.
53 changes: 35 additions & 18 deletions PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,17 +390,25 @@ class PBR_Renderer

virtual ~PBR_Renderer();

// clang-format off
IRenderDevice* GetDevice() const { return m_Device; }
ITextureView* GetIrradianceCubeSRV() const { return m_pIrradianceCubeSRV; }
ITextureView* GetPrefilteredEnvMapSRV() const { return m_pPrefilteredEnvMapSRV; }
ITextureView* GetPreintegratedGGX_SRV() const { return m_pPreintegratedGGX_SRV; }
ITextureView* GetWhiteTexSRV() const { return m_pWhiteTexSRV; }
ITextureView* GetBlackTexSRV() const { return m_pBlackTexSRV; }
ITextureView* GetDefaultNormalMapSRV() const { return m_pDefaultNormalMapSRV; }
IBuffer* GetPBRPrimitiveAttribsCB() const {return m_PBRPrimitiveAttribsCB;}
IBuffer* GetJointsBuffer() const {return m_JointsBuffer;}
// clang-format on
IRenderDevice* GetDevice() const { return m_Device; }

ITextureView* GetConvertedEnvironmentCubeMap() const { return m_pConvertedEnvironmentCubeSRV; }

ITextureView* GetIrradianceCubeSRV() const { return m_pIrradianceCubeSRV; }

ITextureView* GetPrefilteredEnvMapSRV() const { return m_pPrefilteredEnvMapSRV; }

ITextureView* GetPreintegratedGGX_SRV() const { return m_pPreintegratedGGX_SRV; }

ITextureView* GetWhiteTexSRV() const { return m_pWhiteTexSRV; }

ITextureView* GetBlackTexSRV() const { return m_pBlackTexSRV; }

ITextureView* GetDefaultNormalMapSRV() const { return m_pDefaultNormalMapSRV; }

IBuffer* GetPBRPrimitiveAttribsCB() const { return m_PBRPrimitiveAttribsCB; }

IBuffer* GetJointsBuffer() const { return m_JointsBuffer; }

/// Precompute cubemaps used by IBL.
void PrecomputeCubemaps(IDeviceContext* pCtx,
Expand All @@ -409,6 +417,7 @@ class PBR_Renderer
Uint32 NumThetaSamples = 32,
bool OptimizeSamples = true);


void CreateResourceBinding(IShaderResourceBinding** ppSRB, Uint32 Idx = 0) const;

#define PSO_FLAG_BIT(Bit) (Uint64{1} << Uint64{Bit})
Expand Down Expand Up @@ -680,15 +689,23 @@ class PBR_Renderer
RefCntAutoPtr<ITextureView> m_pDefaultNormalMapSRV;
RefCntAutoPtr<ITextureView> m_pDefaultPhysDescSRV;

static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA32_FLOAT;
static constexpr TEXTURE_FORMAT EnvironmentCubeFmt = TEX_FORMAT_RGBA16_FLOAT;
static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA16_FLOAT;
static constexpr TEXTURE_FORMAT PrefilteredEnvMapFmt = TEX_FORMAT_RGBA16_FLOAT;
static constexpr Uint32 IrradianceCubeDim = 64;
static constexpr Uint32 PrefilteredEnvMapDim = 256;

RefCntAutoPtr<ITextureView> m_pIrradianceCubeSRV;
RefCntAutoPtr<ITextureView> m_pPrefilteredEnvMapSRV;
RefCntAutoPtr<IPipelineState> m_pPrecomputeIrradianceCubePSO;
RefCntAutoPtr<IPipelineState> m_pPrefilterEnvMapPSO;
static constexpr Uint32 EnvironmentCubeDim = 512;
static constexpr Uint32 IrradianceCubeDim = 64;
static constexpr Uint32 PrefilteredEnvMapDim = 256;

RefCntAutoPtr<ITextureView> m_pConvertedEnvironmentCubeSRV;
RefCntAutoPtr<ITextureView> m_pIrradianceCubeSRV;
RefCntAutoPtr<ITextureView> m_pPrefilteredEnvMapSRV;

RefCntAutoPtr<IPipelineState> m_pTransformSphereMapToCubeMapPSO;
RefCntAutoPtr<IPipelineState> m_pPrecomputeIrradianceCubePSO;
RefCntAutoPtr<IPipelineState> m_pPrefilterEnvMapPSO;

RefCntAutoPtr<IShaderResourceBinding> m_pTransformSphereMapToCubeMapSRB;
RefCntAutoPtr<IShaderResourceBinding> m_pPrecomputeIrradianceCubeSRB;
RefCntAutoPtr<IShaderResourceBinding> m_pPrefilterEnvMapSRB;

Expand Down
109 changes: 106 additions & 3 deletions PBR/src/PBR_Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ std::string PBR_Renderer::GetPSOFlagsString(PSO_FLAGS Flags)
const PSO_FLAGS Flag = ExtractLSB(Flags);
switch (Flag)
{
// clang-format off
// clang-format off
case PSO_FLAG_USE_COLOR_MAP: FlagsStr += "COLOR_MAP"; break;
case PSO_FLAG_USE_NORMAL_MAP: FlagsStr += "NORMAL_MAP"; break;
case PSO_FLAG_USE_PHYS_DESC_MAP: FlagsStr += "PHYS_DESC_MAP"; break;
Expand Down Expand Up @@ -234,6 +234,14 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice,

auto PrefilteredEnvMapTex = m_Device.CreateTexture(TexDesc);
m_pPrefilteredEnvMapSRV = PrefilteredEnvMapTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);

TexDesc.Name = "Converted environment map for PBR renderer";
TexDesc.Width = EnvironmentCubeDim;
TexDesc.Height = EnvironmentCubeDim;
TexDesc.Format = EnvironmentCubeFmt;

auto ConvertedEnvMapTex = m_Device.CreateTexture(TexDesc);
m_pConvertedEnvironmentCubeSRV = ConvertedEnvMapTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
}

if (m_Settings.CreateDefaultTextures)
Expand Down Expand Up @@ -489,6 +497,59 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
CreateUniformBuffer(m_Device, sizeof(PrecomputeEnvMapAttribs), "Precompute env map attribs CB", &m_PrecomputeEnvMapAttribsCB);
}

if (!m_pTransformSphereMapToCubeMapPSO)
{
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
ShaderCI.pShaderSourceStreamFactory = &DiligentFXShaderSourceStreamFactory::GetInstance();

RefCntAutoPtr<IShader> pVS;
{
ShaderCI.Desc = {"Cubemap face VS", SHADER_TYPE_VERTEX, true};
ShaderCI.EntryPoint = "main";
ShaderCI.FilePath = "CubemapFace.vsh";

pVS = m_Device.CreateShader(ShaderCI);
}

// Create pixel shader
RefCntAutoPtr<IShader> pPS;
{
ShaderCI.Desc = {"Transform sphere map to cube map PS", SHADER_TYPE_PIXEL, true};
ShaderCI.EntryPoint = "main";
ShaderCI.FilePath = "TransformSpheremapToCubemap.psh";

pPS = m_Device.CreateShader(ShaderCI);
}

GraphicsPipelineStateCreateInfo PSOCreateInfo;
PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;

PSODesc.Name = "Transform sphere map to cube map PSO";
PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS;

GraphicsPipeline.NumRenderTargets = 1;
GraphicsPipeline.RTVFormats[0] = IrradianceCubeFmt;
GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
GraphicsPipeline.DepthStencilDesc.DepthEnable = False;

PSOCreateInfo.pVS = pVS;
PSOCreateInfo.pPS = pPS;

PipelineResourceLayoutDescX ResourceLayout;
ResourceLayout
.SetDefaultVariableType(SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
.AddVariable(SHADER_TYPE_PIXEL, "g_EnvironmentMap", SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
.AddImmutableSampler(SHADER_TYPE_PIXEL, "g_EnvironmentMap", Sam_LinearWrap);
PSODesc.ResourceLayout = ResourceLayout;

Check warning

Code scanning / PREfast

Do not slice (es.63). Warning

Do not slice (es.63).

m_pTransformSphereMapToCubeMapPSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
m_pTransformSphereMapToCubeMapPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbTransform")->Set(m_PrecomputeEnvMapAttribsCB);
m_pTransformSphereMapToCubeMapPSO->CreateShaderResourceBinding(&m_pTransformSphereMapToCubeMapSRB, true);
}

if (!m_pPrecomputeIrradianceCubePSO)
{
ShaderCreateInfo ShaderCI;
Expand Down Expand Up @@ -617,8 +678,50 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
};
// clang-format on

bool IsCubeMap = pEnvironmentMap->GetTexture()->GetDesc().IsCube();

if (!IsCubeMap)
{
pCtx->SetPipelineState(m_pTransformSphereMapToCubeMapPSO);
m_pTransformSphereMapToCubeMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap);
pCtx->CommitShaderResources(m_pTransformSphereMapToCubeMapSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);

auto* pConvertedEnvCube = m_pConvertedEnvironmentCubeSRV->GetTexture();
const auto& ConvertedEnvCubDesc = pConvertedEnvCube->GetDesc();
for (Uint32 mip = 0; mip < ConvertedEnvCubDesc.MipLevels; ++mip)
{
for (Uint32 face = 0; face < 6; ++face)
{
TextureViewDesc RTVDesc{"RTV for converted environment texture", TEXTURE_VIEW_RENDER_TARGET, RESOURCE_DIM_TEX_2D_ARRAY};
RTVDesc.MostDetailedMip = mip;
RTVDesc.FirstArraySlice = face;
RTVDesc.NumArraySlices = 1;
RefCntAutoPtr<ITextureView> pRTV;
pConvertedEnvCube->CreateView(RTVDesc, &pRTV);
ITextureView* ppRTVs[] = {pRTV};
pCtx->SetRenderTargets(_countof(ppRTVs), ppRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
{
MapHelper<PrecomputeEnvMapAttribs> Attribs{pCtx, m_PrecomputeEnvMapAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD};
Attribs->Rotation = Matrices[face];
}
DrawAttribs drawAttrs(4, DRAW_FLAG_VERIFY_ALL);
pCtx->Draw(drawAttrs);
}
}

// clang-format off
StateTransitionDesc Barriers[] =
{
{m_pConvertedEnvironmentCubeSRV->GetTexture(), RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_SHADER_RESOURCE, STATE_TRANSITION_FLAG_UPDATE_STATE},
};
// clang-format on
pCtx->TransitionResourceStates(_countof(Barriers), Barriers);
}

auto* pEnvironmentCube = IsCubeMap ? pEnvironmentMap : m_pConvertedEnvironmentCubeSRV;

pCtx->SetPipelineState(m_pPrecomputeIrradianceCubePSO);
m_pPrecomputeIrradianceCubeSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap);
m_pPrecomputeIrradianceCubeSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentCube);
pCtx->CommitShaderResources(m_pPrecomputeIrradianceCubeSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
auto* pIrradianceCube = m_pIrradianceCubeSRV->GetTexture();
const auto& IrradianceCubeDesc = pIrradianceCube->GetDesc();
Expand All @@ -644,7 +747,7 @@ void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx,
}

pCtx->SetPipelineState(m_pPrefilterEnvMapPSO);
m_pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentMap);
m_pPrefilterEnvMapSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_EnvironmentMap")->Set(pEnvironmentCube);
pCtx->CommitShaderResources(m_pPrefilterEnvMapSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
auto* pPrefilteredEnvMap = m_pPrefilteredEnvMapSRV->GetTexture();
const auto& PrefilteredEnvMapDesc = pPrefilteredEnvMap->GetDesc();
Expand Down
3 changes: 2 additions & 1 deletion Shaders/PBR/private/ComputeIrradianceMap.psh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ void main(in float4 Pos : SV_Position,
in float3 WorldPos : WORLD_POS,
out float4 Color : SV_Target)
{
float3 N = normalize(WorldPos);

float3 N = normalize(WorldPos);
float3 up = float3(0.0, 1.0, 0.0);
float3 right = normalize(cross(up, N));
up = cross(N, right);
Expand Down
20 changes: 20 additions & 0 deletions Shaders/PBR/private/TransformSpheremapToCubemap.psh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "PBR_PrecomputeCommon.fxh"

Texture2D<float4> g_EnvironmentMap;
SamplerState g_EnvironmentMap_sampler;

float2 TransformDirectionToSpherePoint(float3 Direction)
{
float Theta = acos(Direction.y);
float Phi = atan2(Direction.x, -Direction.z);
return -rcp(PI) * float2(0.5 * Phi, Theta);
}

float4 main(in float4 Pos : SV_Position,
in float3 WorldPos : WORLD_POS) : SV_Target0
{
float3 Direction = normalize(WorldPos);
float2 SamplePoint = TransformDirectionToSpherePoint(Direction);
float4 Color = g_EnvironmentMap.SampleLevel(g_EnvironmentMap_sampler, SamplePoint, 0.0);
return float4(Color.xyz, 1.0);
}

0 comments on commit 2bfba45

Please sign in to comment.