Optimize environment probes filtering shader

This commit is contained in:
Wojtek Figat
2025-07-03 11:45:12 +02:00
parent 33e58c12cb
commit a138c6b062
3 changed files with 42 additions and 18 deletions

BIN
Content/Shaders/ProbesFilter.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -125,11 +125,21 @@ public:
}
bool LazyInit();
bool InitShader();
void Update() override;
void Dispose() override;
void Bake(const ProbeEntry& e);
private:
void OnRender(RenderTask* task, GPUContext* context);
#if COMPILE_WITH_DEV_ENV
bool _initShader = false;
void OnShaderReloading(Asset* obj)
{
_initShader = true;
SAFE_DELETE_GPU_RESOURCE(_psFilterFace);
}
#endif
};
ProbesRendererService ProbesRendererServiceInstance;
@@ -206,19 +216,13 @@ bool ProbesRendererService::LazyInit()
_initFailed = _shader == nullptr;
if (_initFailed)
return false;
#if COMPILE_WITH_DEV_ENV
_shader->OnReloading.Bind<ProbesRendererService, &ProbesRendererService::OnShaderReloading>(this);
#endif
}
if (!_shader->IsLoaded())
return true;
const auto shader = _shader->GetShader();
CHECK_INVALID_SHADER_PASS_CB_SIZE(shader, 0, Data);
// Create pipeline stages
_psFilterFace = GPUDevice::Instance->CreatePipelineState();
auto psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
{
psDesc.PS = shader->GetPS("PS_FilterFace");
_initFailed |= _psFilterFace->Init(psDesc);
}
_initFailed |= InitShader();
// Init rendering pipeline
_output = GPUDevice::Instance->CreateTexture(TEXT("ProbesRenderer.Output"));
@@ -262,6 +266,16 @@ bool ProbesRendererService::LazyInit()
return false;
}
bool ProbesRendererService::InitShader()
{
const auto shader = _shader->GetShader();
CHECK_INVALID_SHADER_PASS_CB_SIZE(shader, 0, Data);
_psFilterFace = GPUDevice::Instance->CreatePipelineState();
auto psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
psDesc.PS = shader->GetPS("PS_FilterFace");
return _psFilterFace->Init(psDesc);
}
void ProbesRendererService::Update()
{
PROFILE_MEM(Graphics);
@@ -412,6 +426,18 @@ void ProbesRendererService::OnRender(RenderTask* task, GPUContext* context)
auto shader = _shader->GetShader();
PROFILE_GPU("Render Probe");
#if COMPILE_WITH_DEV_ENV
// handle shader hot-reload
if (_initShader)
{
if (_shader->WaitForLoaded())
return;
_initShader = false;
if (InitShader())
return;
}
#endif
// Init
const int32 probeResolution = _current.GetResolution();
const PixelFormat probeFormat = _current.GetFormat();

View File

@@ -50,18 +50,16 @@ float4 PS_FilterFace(Quad_VS2PS input) : SV_Target
float2 uv = input.TexCoord * 2 - 1;
float3 cubeCoordinates = UvToCubeMapUv(uv);
#define NUM_FILTER_SAMPLES 512
float3 N = normalize(cubeCoordinates);
float roughness = ProbeRoughnessFromMip(SourceMipIndex);
const uint samplesCount = roughness > 0.1 ? 64 : 32;
float4 filteredColor = 0;
float weight = 0;
LOOP
for (int i = 0; i < NUM_FILTER_SAMPLES; i++)
for (int i = 0; i < samplesCount; i++)
{
float2 E = Hammersley(i, NUM_FILTER_SAMPLES, 0);
float2 E = Hammersley(i, samplesCount, 0);
float3 H = TangentToWorld(ImportanceSampleGGX(E, roughness).xyz, N);
float3 L = 2 * dot(N, H) * H - N;
float NoL = saturate(dot(N, L));