From 3848300cb4c3dd43f9825100afee19c919c6cf6f Mon Sep 17 00:00:00 2001 From: rapt0r Date: Thu, 2 Apr 2026 20:46:44 -0700 Subject: [PATCH 01/18] DXSSAOContext - Shader must be implemented. --- Engine/include/DXRenderManager.hpp | 2 + Engine/include/DXSSAOContext.hpp | 69 +++++++++ Engine/source/DXSSAOContext.cpp | 239 +++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 Engine/include/DXSSAOContext.hpp create mode 100644 Engine/source/DXSSAOContext.cpp diff --git a/Engine/include/DXRenderManager.hpp b/Engine/include/DXRenderManager.hpp index 0a780a14..b4f3ac54 100644 --- a/Engine/include/DXRenderManager.hpp +++ b/Engine/include/DXRenderManager.hpp @@ -23,6 +23,7 @@ #include "DX2DRenderContext.hpp" #include "DXForwardRenderContext.hpp" #include "DXGBufferContext.hpp" +#include "DXSSAOContext.hpp" #include "DXNaiveLightingContext.hpp" #include "DXGlobalLightingContext.hpp" #include "DXLocalLightingContext.hpp" @@ -40,6 +41,7 @@ class DXRenderManager : public RenderManager friend class DX2DRenderContext; friend class DXForwardRenderContext; friend class DXGBufferContext; + friend class DXSSAOContext; friend class DXNaiveLightingContext; friend class DXGlobalLightingContext; friend class DXLocalLightingContext; diff --git a/Engine/include/DXSSAOContext.hpp b/Engine/include/DXSSAOContext.hpp new file mode 100644 index 00000000..de6fc760 --- /dev/null +++ b/Engine/include/DXSSAOContext.hpp @@ -0,0 +1,69 @@ +//Author: JEYOON YU +//Project: CubeEngine +//File: DXSSAOContext.hpp +#pragma once +#include "Interface/IRenderContext.hpp" + +#include "DXPipeLine.hpp" +#include + +class DXRenderManager; + +class DXSSAOContext : public IRenderContext +{ +public: + DXSSAOContext(DXRenderManager* renderManager) : m_renderManager(renderManager) {} + ~DXSSAOContext() override = default; + + void Initialize() override; + void OnResize() override; + void Execute(ICommandListWrapper* commandListWrapper) override; + void CleanUp() override; + + UINT GetBlurredAOSrvIndex() const { return m_blurSrvHandle.second; } + + void DrawImGui(); +private: + DXRenderManager* m_renderManager; + + // SSAO Pass Resource + ComPtr m_ssaoTexture; // R8_UNORM + ComPtr m_ssaoRtvHeap; + std::pair m_ssaoSrvHandle; + ComPtr m_ssaoRootSignature; + std::unique_ptr m_ssaoPipeline; + + // Blur Pass Resource + ComPtr m_blurTexture; // R8_UNORM + ComPtr m_blurRtvHeap; + std::pair m_blurSrvHandle; + ComPtr m_blurRootSignature; + std::unique_ptr m_blurPipeline; + + std::pair m_gBufferSrvHandle; + + // Push Constants for SSAO + struct alignas(16) PushConstants + { + glm::mat4 inverseProjection; + float radius; + float scale; + float contrast; + int numSamples; + float delta; + float screenWidth; + float screenHeight; + } pushConstants; + + // ImGui Parameters + float m_radius = 1.0f; + float m_scale = 1.0f; + float m_contrast = 1.0f; + int m_numSamples = 15; + float m_delta = 0.001f; + bool m_enabled = true; + + // Helper Functions + void CreateSSAOResources(); + void CreateBlurResources(); +}; diff --git a/Engine/source/DXSSAOContext.cpp b/Engine/source/DXSSAOContext.cpp new file mode 100644 index 00000000..f83a4266 --- /dev/null +++ b/Engine/source/DXSSAOContext.cpp @@ -0,0 +1,239 @@ +//Author: JEYOON YU +//Project: CubeEngine +//File: DXSSAOContext.cpp +#include "DXSSAOContext.hpp" + +#include + +#include "DXCommandListWrapper.hpp" +#include "DXRenderManager.hpp" +#include "DXSkyboxRenderContext.hpp" +#include "Engine.hpp" + +void DXSSAOContext::Initialize() +{ + CreateSSAOResources(); + CreateBlurResources(); + + m_gBufferSrvHandle = m_renderManager->AllocateSrvHandles(4); + D3D12_CPU_DESCRIPTOR_HANDLE destHandle = m_gBufferSrvHandle.first; + D3D12_CPU_DESCRIPTOR_HANDLE srcHandle = m_renderManager->GetGBufferContext()->GetSRVHeap()->GetCPUDescriptorHandleForHeapStart(); + m_renderManager->m_device->CopyDescriptorsSimple(4, destHandle, srcHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + // SSAO Root Signature & Pipeline + std::vector rootParameters(2); + rootParameters[0].InitAsConstants(sizeof(PushConstants) / 4, 0, 0, D3D12_SHADER_VISIBILITY_PIXEL);; + CD3DX12_DESCRIPTOR_RANGE1 gBufferRange; + gBufferRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 0, 0); + rootParameters[1].InitAsDescriptorTable(1, &gBufferRange, D3D12_SHADER_VISIBILITY_PIXEL); + + m_renderManager->CreateRootSignature(m_ssaoRootSignature, rootParameters); + DXHelper::ThrowIfFailed(m_ssaoRootSignature->SetName(L"SSAO Root Signature")); + + std::vector rtvFormats = { DXGI_FORMAT_R8_UNORM }; + m_ssaoPipeline = DXPipeLineBuilder(m_renderManager->m_device, m_ssaoRootSignature) + .SetShaders("../Engine/shaders/hlsl/SSAO.vert.hlsl", "../Engine/shaders/hlsl/SSAO.frag.hlsl") + .SetLayout(std::initializer_list{}) + .SetRasterizer(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, false) + .SetDepthStencil(false, false) + .SetRenderTargets(rtvFormats) + .SetTopology(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE) + .Build(); + + // Blur Root Signature & Pipeline + rootParameters.resize(3); + rootParameters[0].InitAsConstants(sizeof(PushConstants) / 4, 0, 0, D3D12_SHADER_VISIBILITY_PIXEL);; + rootParameters[1].InitAsDescriptorTable(1, &gBufferRange, D3D12_SHADER_VISIBILITY_PIXEL); + CD3DX12_DESCRIPTOR_RANGE1 ssaoRange; + ssaoRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 4, 0); + rootParameters[2].InitAsDescriptorTable(1, &ssaoRange, D3D12_SHADER_VISIBILITY_PIXEL); + + m_renderManager->CreateRootSignature(m_blurRootSignature, rootParameters); + DXHelper::ThrowIfFailed(m_blurRootSignature->SetName(L"SSAO Blur Root Signature")); + + m_blurPipeline = DXPipeLineBuilder(m_renderManager->m_device, m_blurRootSignature) + .SetShaders("../Engine/shaders/hlsl/SSAO.vert.hlsl", "../Engine/shaders/hlsl/SSAOBlur.frag.hlsl") + .SetLayout(std::initializer_list{}) + .SetRasterizer(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, false) + .SetDepthStencil(false, false) + .SetRenderTargets(rtvFormats) + .SetTopology(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE) + .Build(); +} + +void DXSSAOContext::OnResize() +{ +} + +void DXSSAOContext::Execute(ICommandListWrapper* commandListWrapper) +{ + if (!m_enabled) return; + + DXCommandListWrapper* dxCommandListWrapper = dynamic_cast(commandListWrapper); + ID3D12GraphicsCommandList10* commandList = dxCommandListWrapper->GetDXCommandList(); + + int width = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderWidth(); + int height = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderHeight(); + + // Set Viewport and Scissor Rect + D3D12_VIEWPORT viewport = { 0.f, 0.f, static_cast(width), static_cast(height), 0.f, 1.f }; + D3D12_RECT scissorRect = { 0, 0, width, height }; + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + // Update Push Constants + pushConstants.inverseProjection = glm::inverse(Engine::GetCameraManager().GetProjectionMatrix()); + pushConstants.radius = m_radius; + pushConstants.scale = m_scale; + pushConstants.contrast = m_contrast; + pushConstants.numSamples = m_numSamples; + pushConstants.delta = m_delta; + pushConstants.screenWidth = static_cast(width); + pushConstants.screenHeight = static_cast(height); + + // Set Descriptor Heaps + ID3D12DescriptorHeap* ppHeaps[] = { m_renderManager->m_srvHeap.Get() }; + commandList->SetDescriptorHeaps(1, ppHeaps); + + // SSAO Pass + auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_ssaoTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + + commandList->SetPipelineState(m_ssaoPipeline->GetPipelineState().Get()); + commandList->SetGraphicsRootSignature(m_ssaoRootSignature.Get()); + + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_ssaoRtvHeap->GetCPUDescriptorHandleForHeapStart(); + commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); + + float clearColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + + commandList->SetGraphicsRoot32BitConstants(0, sizeof(PushConstants) / 4, &pushConstants, 0); + D3D12_GPU_DESCRIPTOR_HANDLE gBufferGpuHandle = m_renderManager->m_srvHeap->GetGPUDescriptorHandleForHeapStart(); + gBufferGpuHandle.ptr += static_cast(m_gBufferSrvHandle.second) * m_renderManager->m_srvDescriptorSize; + commandList->SetGraphicsRootDescriptorTable(1, gBufferGpuHandle); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->DrawInstanced(3, 1, 0, 0); + + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_ssaoTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + commandList->ResourceBarrier(1, &barrier); + + // Bilateral Blur Pass + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + + commandList->SetPipelineState(m_blurPipeline->GetPipelineState().Get()); + commandList->SetGraphicsRootSignature(m_blurRootSignature.Get()); + + rtvHandle = m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart(); + commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); + commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + + commandList->SetGraphicsRoot32BitConstants(0, sizeof(PushConstants) / 4, &pushConstants, 0); + commandList->SetGraphicsRootDescriptorTable(1, gBufferGpuHandle); + D3D12_GPU_DESCRIPTOR_HANDLE ssaoSrvGpuHandle = m_renderManager->m_srvHeap->GetGPUDescriptorHandleForHeapStart(); + ssaoSrvGpuHandle.ptr += static_cast(m_ssaoSrvHandle.second) * m_renderManager->m_srvDescriptorSize; + commandList->SetGraphicsRootDescriptorTable(2, ssaoSrvGpuHandle); + + commandList->DrawInstanced(3, 1, 0, 0); + + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + commandList->ResourceBarrier(1, &barrier); +} + +void DXSSAOContext::CleanUp() +{ +} + +void DXSSAOContext::CreateSSAOResources() +{ + const int width = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderWidth(); + const int height = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderHeight(); + + // 1. Create SSAO Render Target + D3D12_RESOURCE_DESC textureDesc = {}; + textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + textureDesc.Width = static_cast(width); + textureDesc.Height = static_cast(height); + textureDesc.DepthOrArraySize = 1; + textureDesc.MipLevels = 1; + textureDesc.Format = DXGI_FORMAT_R8_UNORM; + textureDesc.SampleDesc.Count = 1; + textureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + D3D12_CLEAR_VALUE clearValue = {}; + clearValue.Format = DXGI_FORMAT_R8_UNORM; + clearValue.Color[0] = 1.0f; + + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + &clearValue, + IID_PPV_ARGS(&m_ssaoTexture) + )); + + // 2. Create RTV Heap for SSAO Render Target + D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; + rtvHeapDesc.NumDescriptors = 1; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_ssaoRtvHeap))); + DXHelper::ThrowIfFailed(m_ssaoRtvHeap->SetName(L"SSAO Render Target View Heap")); + + // 3. Create RTV for SSAO Render Target + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_ssaoRtvHeap->GetCPUDescriptorHandleForHeapStart()); + m_renderManager->m_device->CreateRenderTargetView(m_ssaoTexture.Get(), nullptr, rtvHandle); + + // Create SRV in Main SRV Heap + m_ssaoSrvHandle = m_renderManager->AllocateSrvHandles(1); + m_renderManager->m_device->CreateShaderResourceView(m_ssaoTexture.Get(), nullptr, m_ssaoSrvHandle.first); +} + +void DXSSAOContext::CreateBlurResources() +{ + const int width = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderWidth(); + const int height = m_renderManager->GetPostProcessContext()->GetFidelityFX()->GetRenderHeight(); + + // 1. Create SSAO Render Target + D3D12_RESOURCE_DESC textureDesc = {}; + textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + textureDesc.Width = static_cast(width); + textureDesc.Height = static_cast(height); + textureDesc.DepthOrArraySize = 1; + textureDesc.MipLevels = 1; + textureDesc.Format = DXGI_FORMAT_R8_UNORM; + textureDesc.SampleDesc.Count = 1; + textureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + D3D12_CLEAR_VALUE clearValue = {}; + clearValue.Format = DXGI_FORMAT_R8_UNORM; + clearValue.Color[0] = 1.0f; + + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + &clearValue, + IID_PPV_ARGS(&m_blurTexture) + )); + + // 2. Create RTV Heap for SSAO Render Target + D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; + rtvHeapDesc.NumDescriptors = 1; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_blurRtvHeap))); + DXHelper::ThrowIfFailed(m_blurRtvHeap->SetName(L"SSAO Blur Render Target View Heap")); + + // 3. Create RTV for SSAO Render Target + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart()); + m_renderManager->m_device->CreateRenderTargetView(m_blurTexture.Get(), nullptr, rtvHandle); + + // Create SRV in Main SRV Heap + m_ssaoSrvHandle = m_renderManager->AllocateSrvHandles(1); + m_renderManager->m_device->CreateShaderResourceView(m_blurTexture.Get(), nullptr, m_ssaoSrvHandle.first); +} From f6e9dcfb23b82c6baad571130ba4b2a1139be31c Mon Sep 17 00:00:00 2001 From: rapt0r Date: Fri, 3 Apr 2026 22:09:56 -0700 Subject: [PATCH 02/18] SSAO Shader - Implemented SSAO & SSAO Bilateral Blur Shaders. --- Engine/include/DXSSAOContext.hpp | 3 +- Engine/shaders/hlsl/SSAO.frag.hlsl | 122 +++++++++++++++++++++ Engine/shaders/hlsl/SSAO.vert.hlsl | 37 +++++++ Engine/shaders/hlsl/SSAOBlur.frag.hlsl | 144 +++++++++++++++++++++++++ Engine/shaders/slang/SSAO.slang | 86 +++++++++++++++ Engine/shaders/slang/SSAOBlur.slang | 76 +++++++++++++ Engine/shaders/spirv/SSAO.frag.spv | Bin 0 -> 6012 bytes Engine/shaders/spirv/SSAO.vert.spv | Bin 0 -> 832 bytes Engine/shaders/spirv/SSAOBlur.frag.spv | Bin 0 -> 6036 bytes Engine/source/DXSSAOContext.cpp | 3 +- shader_compiler.py | 5 + 11 files changed, 474 insertions(+), 2 deletions(-) create mode 100644 Engine/shaders/hlsl/SSAO.frag.hlsl create mode 100644 Engine/shaders/hlsl/SSAO.vert.hlsl create mode 100644 Engine/shaders/hlsl/SSAOBlur.frag.hlsl create mode 100644 Engine/shaders/slang/SSAO.slang create mode 100644 Engine/shaders/slang/SSAOBlur.slang create mode 100644 Engine/shaders/spirv/SSAO.frag.spv create mode 100644 Engine/shaders/spirv/SSAO.vert.spv create mode 100644 Engine/shaders/spirv/SSAOBlur.frag.spv diff --git a/Engine/include/DXSSAOContext.hpp b/Engine/include/DXSSAOContext.hpp index de6fc760..e5e7b360 100644 --- a/Engine/include/DXSSAOContext.hpp +++ b/Engine/include/DXSSAOContext.hpp @@ -45,7 +45,8 @@ class DXSSAOContext : public IRenderContext // Push Constants for SSAO struct alignas(16) PushConstants { - glm::mat4 inverseProjection; + glm::mat4 view; + glm::mat4 projection; float radius; float scale; float contrast; diff --git a/Engine/shaders/hlsl/SSAO.frag.hlsl b/Engine/shaders/hlsl/SSAO.frag.hlsl new file mode 100644 index 00000000..ffa6ba88 --- /dev/null +++ b/Engine/shaders/hlsl/SSAO.frag.hlsl @@ -0,0 +1,122 @@ +#pragma pack_matrix(column_major) +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif + +#ifndef __DXC_VERSION_MAJOR +// warning X3557: loop doesn't seem to do anything, forcing loop to unroll +#pragma warning(disable : 3557) +#endif + + +#line 42 "slang/SSAO.slang" +Texture2D gPosition_0 : register(t2, space1); + +SamplerState gSampler_0 : register(s0, space1); + + +#line 41 +Texture2D gNormal_0 : register(t1, space1); + + +#line 22 +struct PushConstants_0 +{ + float4x4 view_0; + float4x4 projection_0; + float radius_0; + float scale_0; + float contrast_0; + int numSamples_0; + float delta_0; + float screenWidth_0; + float screenHeight_0; +}; + +cbuffer pushConstants_0 : register(b0) +{ + PushConstants_0 pushConstants_0; +} + +#line 3 +struct VSOutput_0 +{ + float4 position_0 : SV_POSITION; + float2 uv_0 : TEXCOORD0; +}; + + +#line 47 +float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET +{ + +#line 47 + VSOutput_0 _S1 = input_0; + + float3 P_0 = gPosition_0.SampleLevel(gSampler_0, input_0.uv_0, 0.0f).xyz; + float3 N_0 = gNormal_0.SampleLevel(gSampler_0, input_0.uv_0, 0.0f).xyz; + + if((length(N_0)) < 0.10000000149011612f) + { + +#line 52 + return (float4)1.0f; + } + + float _S2 = mul(pushConstants_0.view_0, float4(P_0, 1.0f)).z; + + int2 _S3 = int2(_S1.position_0.xy); + int _S4 = _S3.x; + +#line 58 + int _S5 = _S3.y; + +#line 58 + float _S6 = float(((int(30) * _S4) ^ _S5) + int(10) * _S4 * _S5); + + + float c_0 = 0.10000000149011612f * pushConstants_0.radius_0; + +#line 61 + int i_0 = int(0); + +#line 61 + float S_0 = 0.0f; + + for(;;) + { + +#line 63 + if(i_0 < (pushConstants_0.numSamples_0)) + { + } + else + { + +#line 63 + break; + } + float alpha_0 = (float(i_0) + 0.5f) / float(pushConstants_0.numSamples_0); + + float theta_0 = 6.28318548202514648f * alpha_0 * (7.0f * float(pushConstants_0.numSamples_0) / 9.0f) + _S6; + +#line 72 + float3 Pi_0 = gPosition_0.SampleLevel(gSampler_0, _S1.uv_0 + alpha_0 * pushConstants_0.radius_0 / _S2 * float2(cos(theta_0), sin(theta_0)) * float2(pushConstants_0.projection_0[int(1)][int(1)] / pushConstants_0.projection_0[int(0)][int(0)], 1.0f) * 0.5f, 0.0f).xyz; + float3 wi_0 = Pi_0 - P_0; + +#line 80 + float S_1 = S_0 + max(0.0f, dot(N_0, wi_0) - pushConstants_0.delta_0 * mul(pushConstants_0.view_0, float4(Pi_0, 1.0f)).z) * step(length(wi_0), pushConstants_0.radius_0) / max(c_0 * c_0, dot(wi_0, wi_0)); + +#line 63 + i_0 = i_0 + int(1); + +#line 63 + S_0 = S_1; + +#line 63 + } + +#line 85 + return (float4)pow(max(0.0f, 1.0f - pushConstants_0.scale_0 * (S_0 * (6.28318548202514648f * c_0 / float(pushConstants_0.numSamples_0)))), pushConstants_0.contrast_0); +} + diff --git a/Engine/shaders/hlsl/SSAO.vert.hlsl b/Engine/shaders/hlsl/SSAO.vert.hlsl new file mode 100644 index 00000000..d3f02e49 --- /dev/null +++ b/Engine/shaders/hlsl/SSAO.vert.hlsl @@ -0,0 +1,37 @@ +#pragma pack_matrix(column_major) +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif + +#ifndef __DXC_VERSION_MAJOR +// warning X3557: loop doesn't seem to do anything, forcing loop to unroll +#pragma warning(disable : 3557) +#endif + + +#line 3 "slang/SSAO.slang" +struct VSOutput_0 +{ + float4 position_0 : SV_POSITION; + float2 uv_0 : TEXCOORD0; +}; + + +VSOutput_0 vertexMain(uint id_0 : SV_VertexID) +{ + VSOutput_0 output_0; + float2 _S1 = float2(float((id_0 << int(1)) & 2U), float(id_0 & 2U)); + +#line 13 + output_0.uv_0 = _S1; + float4 _S2 = float4(_S1 * 2.0f - 1.0f, 0.0f, 1.0f); + +#line 14 + output_0.position_0 = _S2; + + + output_0.position_0[int(1)] = - _S2.y; + + return output_0; +} + diff --git a/Engine/shaders/hlsl/SSAOBlur.frag.hlsl b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl new file mode 100644 index 00000000..8ca86be6 --- /dev/null +++ b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl @@ -0,0 +1,144 @@ +#pragma pack_matrix(column_major) +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif + +#ifndef __DXC_VERSION_MAJOR +// warning X3557: loop doesn't seem to do anything, forcing loop to unroll +#pragma warning(disable : 3557) +#endif + + +#line 9 "slang/SSAOBlur.slang" +struct PushConstants_0 +{ + float4x4 view_0; + float4x4 projection_0; + float radius_0; + float scale_0; + float contrast_0; + int numSamples_0; + float delta_0; + float screenWidth_0; + float screenHeight_0; +}; + +cbuffer pushConstants_0 : register(b0) +{ + PushConstants_0 pushConstants_0; +} + + +Texture2D gNormal_0 : register(t1, space1); + + + +SamplerState gSampler_0 : register(s0, space1); + + +#line 29 +Texture2D gPosition_0 : register(t2, space1); + +Texture2D SSAO_0 : register(t4, space1); + + +#line 3 +struct VSOutput_0 +{ + float4 position_0 : SV_POSITION; + float2 uv_0 : TEXCOORD0; +}; + + +#line 35 +float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET +{ + +#line 35 + VSOutput_0 _S1 = input_0; + + float2 _S2 = 1.0f / float2(pushConstants_0.screenWidth_0, pushConstants_0.screenHeight_0); + float3 centerN_0 = gNormal_0.SampleLevel(gSampler_0, input_0.uv_0, 0.0f).xyz; + if((length(centerN_0)) < 0.10000000149011612f) + { + +#line 39 + return (float4)1.0f; + } + + float _S3 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, _S1.uv_0, 0.0f).xyz, 1.0f)).z; + +#line 42 + int x_0 = int(-2); + +#line 42 + float result_0 = 0.0f; + +#line 42 + float weightSum_0 = 0.0f; + +#line 48 + for(;;) + { + +#line 48 + if(x_0 <= int(2)) + { + } + else + { + +#line 48 + break; + } + +#line 48 + int y_0 = int(-2); + + for(;;) + { + +#line 50 + if(y_0 <= int(2)) + { + } + else + { + +#line 50 + break; + } + + float2 sampleUV_0 = _S1.uv_0 + float2(float(x_0), float(y_0)) * _S2; + +#line 63 + float depthDiff_0 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, 1.0f)).z - _S3; + +#line 68 + float weight_0 = exp(float(- (x_0 * x_0 + y_0 * y_0)) / 8.0f) * (max(0.0f, dot(gNormal_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, centerN_0)) * (1.0f / sqrt(0.06283184140920639f) * exp(- (depthDiff_0 * depthDiff_0) / 0.01999999955296516f))); + + float result_1 = result_0 + SSAO_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).x * weight_0; + float weightSum_1 = weightSum_0 + weight_0; + +#line 50 + y_0 = y_0 + int(1); + +#line 50 + result_0 = result_1; + +#line 50 + weightSum_0 = weightSum_1; + +#line 50 + } + +#line 48 + x_0 = x_0 + int(1); + +#line 48 + } + +#line 75 + return (float4)(result_0 / max(weightSum_0, 0.00009999999747379f)); +} + diff --git a/Engine/shaders/slang/SSAO.slang b/Engine/shaders/slang/SSAO.slang new file mode 100644 index 00000000..e5467281 --- /dev/null +++ b/Engine/shaders/slang/SSAO.slang @@ -0,0 +1,86 @@ +#define PI 3.14159265358979323846f + +struct VSOutput +{ + float4 position : SV_POSITION; + float2 uv : TEXCOORD0; +}; + +[shader("vertex")] +VSOutput vertexMain(uint id : SV_VertexID) +{ + VSOutput output; + output.uv = float2((id << 1) & 2, id & 2); + output.position = float4(output.uv * 2.0f - 1.0f, 0.0f, 1.0f); + // Invert Y for DirectX coordinate system +#if defined(__hlsl__) + output.position.y = -output.position.y; +#endif + return output; +} + +struct PushConstants +{ + float4x4 view; + float4x4 projection; + float radius; + float scale; + float contrast; + int numSamples; + float delta; + float screenWidth; + float screenHeight; +} +#if defined(__hlsl__) +ConstantBuffer pushConstants : register(b0, space0); +#else +[[vk::push_constant]] PushConstants pushConstants; +#endif + +Texture2D gAlbedo : register(t0, space1); +Texture2D gNormal : register(t1, space1); +Texture2D gPosition : register(t2, space1); +Texture2D gMaterial : register(t3, space1); +SamplerState gSampler : register(s0, space1); + +[shader("fragment")] +float4 fragmentMain(VSOutput input) : SV_Target +{ + float3 P = gPosition.SampleLevel(gSampler, input.uv, 0).xyz; + float3 N = gNormal.SampleLevel(gSampler, input.uv, 0).xyz; + // Ignore skybox pixels with near-zero normals + if (length(N) < 0.1f) return 1.0f; + + float4 viewPosition = mul(pushConstants.view, float4(P, 1.0f)); + float d = viewPosition.z; + + int2 coord = int2(input.position.xy); + float phi = (float)(((30 * coord.x) ^ coord.y) + 10 * coord.x * coord.y); + + float S = 0.0f; + float c = 0.1f * pushConstants.radius; + + for (int i = 0; i < pushConstants.numSamples; ++i) + { + float alpha = ((float)i + 0.5f) / (float)pushConstants.numSamples; + float h = alpha * pushConstants.radius / d; + float theta = 2.f * PI * alpha * (7.0f * (float)pushConstants.numSamples / 9.0f) + phi; + + float2 offset = h * float2(cos(theta), sin(theta)); + float2 sampleUV = input.uv + offset * float2(pushConstants.projection[1][1] / pushConstants.projection[0][0], 1.0f) * 0.5f; + + float3 Pi = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; + float3 wi = Pi - P; + float di = mul(pushConstants.view, float4(Pi, 1.0f)).z; + float heaviside = step(length(wi), pushConstants.radius); + + float numerator = max(0.0f, dot(N, wi) - pushConstants.delta * di) * heaviside; + float denominator = max(c * c, dot(wi, wi)); + + S += numerator / denominator; + } + + S *= (2.0f * PI * c) / (float)pushConstants.numSamples; + float A = pow(max(0.0f, 1.0f - pushConstants.scale * S), pushConstants.contrast); + return A; +} diff --git a/Engine/shaders/slang/SSAOBlur.slang b/Engine/shaders/slang/SSAOBlur.slang new file mode 100644 index 00000000..6c478774 --- /dev/null +++ b/Engine/shaders/slang/SSAOBlur.slang @@ -0,0 +1,76 @@ +#define PI 3.14159265358979323846f + +struct VSOutput +{ + float4 position : SV_POSITION; + float2 uv : TEXCOORD0; +}; + +struct PushConstants +{ + float4x4 view; + float4x4 projection; + float radius; + float scale; + float contrast; + int numSamples; + float delta; + float screenWidth; + float screenHeight; +} +#if defined(__hlsl__) +ConstantBuffer pushConstants : register(b0, space0); +#else +[[vk::push_constant]] PushConstants pushConstants; +#endif + +Texture2D gAlbedo : register(t0, space1); +Texture2D gNormal : register(t1, space1); +Texture2D gPosition : register(t2, space1); +Texture2D gMaterial : register(t3, space1); +Texture2D SSAO : register(t4, space1); +SamplerState gSampler : register(s0, space1); + +[shader("fragment")] +float4 fragmentMain(VSOutput input) : SV_Target +{ + float2 texelSize = 1.0f / float2(pushConstants.screenWidth, pushConstants.screenHeight); + float3 centerN = gNormal.SampleLevel(gSampler, input.uv, 0).xyz; + if (length(centerN) < 0.1f) return 1.0f; + + float3 centerP = gPosition.SampleLevel(gSampler, input.uv, 0).xyz; + float centerD = mul(pushConstants.view, float4(centerP, 1.0f)).z; + + float result = 0.0f; + float weightSum = 0.0f; + float variance = 0.01f; + + for (int x = -2; x <= 2; ++x) + { + for (int y = -2; y <= 2; ++y) + { + float2 offset = float2(x, y) * texelSize; + float2 sampleUV = input.uv + offset; + + float sampleAO = SSAO.SampleLevel(gSampler, sampleUV, 0).r; + float3 sampleN = gNormal.SampleLevel(gSampler, sampleUV, 0).xyz; + float3 sampleP = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; + float sampleD = mul(pushConstants.view, float4(sampleP, 1.0f)).z; + + float spatialWeight = exp(-(x * x + y * y) / 8.0f); + + float normalTerm = max(0.0f, dot(sampleN, centerN)); + float depthDiff = sampleD - centerD; + float depthTerm = (1.0f / sqrt(2.0f * 3.141592f * variance)) * exp(-(depthDiff * depthDiff) / (2.0f * variance)); + + float rangeWeight = normalTerm * depthTerm; + + float weight = spatialWeight * rangeWeight; + + result += sampleAO * weight; + weightSum += weight; + } + } + + return result / max(weightSum, 0.0001f); +} diff --git a/Engine/shaders/spirv/SSAO.frag.spv b/Engine/shaders/spirv/SSAO.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..e885a752549075e5de5cfe34cf75b6f92c79d39a GIT binary patch literal 6012 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 literal 0 HcmV?d00001 diff --git a/Engine/shaders/spirv/SSAOBlur.frag.spv b/Engine/shaders/spirv/SSAOBlur.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d06506e066c1e7b85c984e03e73f4e68330d9ca9 GIT binary patch literal 6036 zcmai%eUQ~<6~}+Ddl!O5FcDOY5HvxFEYU#?gg{>6#g#=Nds%P0cj40RUb=gim;O*1 zp~$HjnsL%;rZO!?hZ-GiAbU0JJ*@1_nPz&M%0HSWwTzOc==1sA=iL24%=9o{&pF?7 zp68tNy!`IkHg?XqtZht|WplGB3dXtF*i3a|){(76u3FciET@{Q`HY!cj=^UucFPjzU=NMpgsPE=~^%;q6`)|VUg>hA7F ztzO<*>FFP+l^Y9pFYH-f8(3f7UaPZh3$JF^I+$U+qp#d3D@)mUc0J3wMuxX7uMG`1 z%0rFeo|w^`qu;T!TG^%S;GdlPxT9X%Ug>RAYwWt~%e&w8a$j|1c$D+BhI`8c6=cl! z%zA4>je2>QogU>&=tCoe-Q~d@1C_!W9q@gXfxPfo!!sQ2tyd~To2z||ZLB>muVH+P zU!9)}Ce?Lh3y?dCz2J3wuI-uUWdjr>j;S zYIK$B<-wkQj(reveY*SJ?faP5yxZ;BgXp#X{^3e~pG(<8tsJ-BhMMO&gzWBKc5~D2 z$R0*HTd$9d^2{q`hgHGB9D4*wiyk)yj9odnVefqqkqkKN^$(HS&v}ez? z>=oFh?0M|I%8tgi71jQJbh#IT+f=E?8+{S3ULM+7+1$J$uJsaJ^DQ>_uL!w68#VpQnJ;)EDn^4z^ZTwCJy6*%9YaR&;VZ%^*S1Jng$Vb3nu zzA^m{{n|yp??%7<=+`d#{l*vf^bof3_GP?w#Gl71V{*U00?nGvC&qqfC3_aOz1o}n zG$QS3R*v@URY-ku(}}$_>DK4m*CEXzum4Jpz$-WrdJ7A35OmcY#(LDx`kn!+&+bmR|(2Z10U15_vtEoW0mv3~h&N zzPYL9u@@1wB=JiVuRVjFmLpxyyso(tINYDrNIB1ADr>AmM%)JUXO16V9QAI&c9{EZ zNc(YbF2Ei^x{t+uejoOKPMtax^Y>!gORT>iefrU77rEYt(5=BWBHlY}zw_Be`BT6> zD&hv_dghk{W3@dCe`Bmq+kNsKIJB1{muWD<@4a?tTZ{MFdcuDQ-Qj(0C(*3jYSyY< z0*?9IFz?<3?5H#P?SwnB@vfy|PioFt687ZWUVZFZ)=-Uew~l{exwqESf%IMpZTp;X zhCQ)h8{b*5jrVUG=l_E)$2RN8{)KKI{uyXKWx)*8=CsA4uGF=sBK{`%Sr@lEr z&izwgLX3CGyZZ{9d#%qHd$X4=U@y_@E$H6I=xr0aoN>{cf1}8stvCN((Jvg)o9E)Y zy&Wt7TYx#|A>R(s_1gX9NQCDoco@{6>|*0 znIky&Y7odfBF7NATro#2am5@v66bnd>3+W#-Tm(c*6;e^tD}1k?vs6(Cw%-lpWOl6 zFZ(fH_!{VC;J(?HdG(DTcLH;|wrd#cJNDdm0q>pPyn~6`op|R(zkAT-?aj9_4(acN z`UIqJRDEL7eKV8MeKX1v+}EkdnZTic3R1sP``lzJwO^fVrT4vryc3xF2`u0BU5VR^ z^j)8iboj3IX`ctoqjX*C(AMX=p7BS3wcA4{GJ2boe9oJO?mVUa%s|ct4*k=S`jy%j zBwML{VX~Fc&p~waML!=!m)i^M=e0he>ri8ob&B|1;{&M zufB>d?+ET|=yK)=?(2!O$KakyTwCJI@eN>(;@o42N3`ZXow#D$HxpOP@vX!ab9@`l z9L2crV9PtAzVD*T6?1$qamBgcPh2s_58%uZoNxX(kat9mXVB$}IewV9VvZjr&h_FO z{9|C^ z*ME-g9a{wAyZ#GwdFMsH&!NlP+dl4E3HeLlw?YK>D|EjPVsDE3HM+6-?&MuM_cuU3 zzAL{?oZk@l{C7akzoFxAw%=o~1v7yDdsFNm(0!L{Kqoyr|Bt}fxnLzQ=I#{#Ji7ht z0g>-d=<*`CKcmb0cYDn zFah}e)P6Z}#zxHF(IRSSetScissorRects(1, &scissorRect); // Update Push Constants - pushConstants.inverseProjection = glm::inverse(Engine::GetCameraManager().GetProjectionMatrix()); + pushConstants.view = Engine::GetCameraManager().GetViewMatrix(); + pushConstants.projection = Engine::GetCameraManager().GetProjectionMatrix(); pushConstants.radius = m_radius; pushConstants.scale = m_scale; pushConstants.contrast = m_contrast; diff --git a/shader_compiler.py b/shader_compiler.py index 250bed8d..4493f3cb 100644 --- a/shader_compiler.py +++ b/shader_compiler.py @@ -40,6 +40,11 @@ # Geometry Pass, Use totally same vertex and mesh shader but different pixel shader { "file": "GBuffer.slang", "entry": "fragmentMain", "stage": "fragment", "profile_hlsl": "sm_5_1", "out_name": "GBuffer.frag" }, { "file": "GBuffer.slang", "entry": "fragmentMain", "stage": "fragment", "profile_hlsl": "sm_6_5", "out_name": "GBufferMesh.frag" }, # Also need to convert to DXIL + # SSAO Pass + { "file": "SSAO.slang", "entry": "vertexMain", "stage": "vertex", "profile_hlsl": "sm_5_1", "out_name": "SSAO.vert" }, + { "file": "SSAO.slang", "entry": "fragmentMain", "stage": "fragment", "profile_hlsl": "sm_5_1", "out_name": "SSAO.frag" }, + # SSAO Bilateral Blur Pass + { "file": "SSAOBlur.slang", "entry": "fragmentMain", "stage": "fragment", "profile_hlsl": "sm_5_1", "out_name": "SSAOBlur.frag" }, # Naive Lighting Pass { "file": "NaiveLightingPass.slang", "entry": "vertexMain", "stage": "vertex", "profile_hlsl": "sm_5_1", "out_name": "NaiveLightingPass.vert" }, { "file": "NaiveLightingPass.slang", "entry": "fragmentMain", "stage": "fragment", "profile_hlsl": "sm_5_1", "out_name": "NaiveLightingPass.frag" }, From 0664e329c1be685d3af14e38a5aafe8757cc3a24 Mon Sep 17 00:00:00 2001 From: rapt0r Date: Fri, 3 Apr 2026 22:11:41 -0700 Subject: [PATCH 03/18] Minor Code Fix --- Engine/source/DXSSAOContext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/DXSSAOContext.cpp b/Engine/source/DXSSAOContext.cpp index 7dc916db..fc82abb1 100644 --- a/Engine/source/DXSSAOContext.cpp +++ b/Engine/source/DXSSAOContext.cpp @@ -235,6 +235,6 @@ void DXSSAOContext::CreateBlurResources() m_renderManager->m_device->CreateRenderTargetView(m_blurTexture.Get(), nullptr, rtvHandle); // Create SRV in Main SRV Heap - m_ssaoSrvHandle = m_renderManager->AllocateSrvHandles(1); - m_renderManager->m_device->CreateShaderResourceView(m_blurTexture.Get(), nullptr, m_ssaoSrvHandle.first); + m_blurSrvHandle = m_renderManager->AllocateSrvHandles(1); + m_renderManager->m_device->CreateShaderResourceView(m_blurTexture.Get(), nullptr, m_blurSrvHandle.first); } From d02c9c2cc64a349f05b4dee7adc6fa6f77644aad Mon Sep 17 00:00:00 2001 From: rapt0r Date: Fri, 3 Apr 2026 22:40:11 -0700 Subject: [PATCH 04/18] Integrated SSAO to DXRenderManager --- Engine/include/DXRenderManager.hpp | 2 + .../shaders/hlsl/GlobalLightingPass.frag.hlsl | 89 +++++++++--------- Engine/shaders/slang/GlobalLightingPass.slang | 5 +- .../shaders/spirv/GlobalLightingPass.frag.spv | Bin 11000 -> 11248 bytes Engine/source/DXGlobalLightingContext.cpp | 10 +- Engine/source/DXRenderManager.cpp | 6 ++ Engine/source/DXSSAOContext.cpp | 10 +- 7 files changed, 75 insertions(+), 47 deletions(-) diff --git a/Engine/include/DXRenderManager.hpp b/Engine/include/DXRenderManager.hpp index b4f3ac54..7a351f58 100644 --- a/Engine/include/DXRenderManager.hpp +++ b/Engine/include/DXRenderManager.hpp @@ -134,6 +134,8 @@ class DXRenderManager : public RenderManager // G-Buffer Render Context std::unique_ptr m_gBufferContext; DXGBufferContext* GetGBufferContext() const { return m_gBufferContext.get(); } + std::unique_ptr m_ssaoContext; + DXSSAOContext* GetSSAOContext() const { return m_ssaoContext.get(); } // Naive Lighting Context std::unique_ptr m_naiveLightingContext; // Global (Directional) Lighting Context diff --git a/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl b/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl index ab4fcc75..03be1d22 100644 --- a/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl +++ b/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl @@ -14,6 +14,7 @@ Texture2D gAlbedo_0 : register(t0, space1); + SamplerState gSampler_0 : register(s0, space1); @@ -45,11 +46,11 @@ Texture2D gPosition_0 : register(t2, space1); Texture2D gMaterial_0 : register(t3, space1); -#line 80 +#line 81 Texture2D shadowMap_0 : register(t3, space2); -#line 81 +#line 82 SamplerState iblSmp_0 : register(s1, space2); @@ -75,19 +76,23 @@ cbuffer directionalLightList_0 : register(b0) fDirectionalLightList_0 directionalLightList_0; } -#line 72 +#line 73 TextureCube irradianceMap_0 : register(t0, space2); -#line 73 +#line 74 TextureCube prefilterMap_0 : register(t1, space2); -#line 74 +#line 75 Texture2D brdfLUT_0 : register(t2, space2); -#line 168 +#line 69 +Texture2D SSAO_0 : register(t4, space1); + + +#line 169 struct MainVectors_0 { float3 worldPosition_0; @@ -99,11 +104,11 @@ struct MainVectors_0 }; -#line 168 +#line 169 MainVectors_0 MainVectors_x24init_0(float3 worldPosition_1, float3 albedo_1, float4 material_1, float3 V_1, float3 N_1, float3 F0_1) { -#line 168 +#line 169 MainVectors_0 _S1; _S1.worldPosition_0 = worldPosition_1; @@ -113,7 +118,7 @@ MainVectors_0 MainVectors_x24init_0(float3 worldPosition_1, float3 albedo_1, flo _S1.N_0 = N_1; _S1.F0_0 = F0_1; -#line 168 +#line 169 return _S1; } @@ -199,19 +204,19 @@ float Hamburger4MSM_0(float4 b_0, float z_f_0) } -#line 158 "slang/GlobalLightingPass.slang" +#line 159 "slang/GlobalLightingPass.slang" float3 F_0(float3 F0_2, float3 V_2, float3 H_0) { return F0_2 + ((float3)1.0f - F0_2) * pow(1.0f - max(dot(V_2, H_0), 0.0f), 5.0f); } -#line 128 +#line 129 float D_0(float alpha_0, float3 N_2, float3 H_1) { float numerator_0 = pow(alpha_0, 2.0f); -#line 136 +#line 137 return numerator_0 / max(3.14159274101257324f * pow(pow(max(dot(N_2, H_1), 0.0f), 2.0f) * (numerator_0 - 1.0f) + 1.0f, 2.0f), 9.99999997475242708e-07f); } @@ -234,13 +239,13 @@ float G_1(float alpha_2, float3 N_4, float3 V_3, float3 L_0) } -#line 179 +#line 180 float3 PBR_0(MainVectors_0 mainVectors_0, float3 lightPosition_0, float3 lightColor_1, int lightIndex_0) { float roughness_0 = mainVectors_0.material_0.y; -#line 187 +#line 188 float3 L_1 = normalize(- lightPosition_0); @@ -250,17 +255,17 @@ float3 PBR_0(MainVectors_0 mainVectors_0, float3 lightPosition_0, float3 lightCo float3 Ks_0 = F_0(mainVectors_0.F0_0, mainVectors_0.V_0, H_2); -#line 200 +#line 201 float alpha_3 = roughness_0 * roughness_0; float _S6 = max(dot(L_1, mainVectors_0.N_0), 0.0f); -#line 209 +#line 210 return ((1.0f - mainVectors_0.material_0.x) * ((float3)1.0f - Ks_0) * (mainVectors_0.albedo_0 / 3.14159274101257324f) + D_0(alpha_3, mainVectors_0.N_0, H_2) * G_1(alpha_3, mainVectors_0.N_0, mainVectors_0.V_0, L_1) * Ks_0 / max(4.0f * max(dot(mainVectors_0.V_0, mainVectors_0.N_0), 0.0f) * _S6, 0.10000000149011612f)) * lightColor_1 * _S6; } -#line 163 +#line 164 float3 Froughness_0(float3 F0_3, float3 V_4, float3 H_3, float roughness_1) { return F0_3 + (max((float3)(1.0f - roughness_1), F0_3) - F0_3) * pow(clamp(1.0f - max(dot(H_3, V_4), 0.0f), 0.0f, 1.0f), 5.0f); @@ -275,11 +280,11 @@ struct VSOutput_0 }; -#line 213 +#line 214 float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET { -#line 213 +#line 214 VSOutput_0 _S7 = input_0; float3 _S8 = (float3)0.0f; @@ -288,20 +293,20 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET if((albedoSample_0.w) < 0.00999999977648258f) { -#line 218 +#line 219 discard; -#line 218 +#line 219 } float3 albedo_2 = albedoSample_0.xyz; if((pushConstants_0.meshletVisualization_0) > int(0)) { -#line 220 +#line 221 return float4(albedo_2, 1.0f); } -#line 221 +#line 222 float3 normal_0 = gNormal_0.Sample(gSampler_0, _S7.uv_0).xyz; float3 worldPosition_2 = gPosition_0.Sample(gSampler_0, _S7.uv_0).xyz; float4 material_2 = gMaterial_0.Sample(gSampler_0, _S7.uv_0); @@ -316,10 +321,10 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET float3 N_5 = normalize(normal_0); MainVectors_0 _S9 = MainVectors_x24init_0(worldPosition_2, albedo_2, material_2, V_5, N_5, F0_4); -#line 233 +#line 234 float shadow_0; -#line 246 +#line 247 if((pushConstants_0.useShadow_0) > int(0)) { @@ -334,63 +339,63 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET shadowUV_0[int(1)] = - projectionCoords_0.y * 0.5f + 0.5f; -#line 264 +#line 265 float z_f_1 = projectionCoords_0.z; -#line 264 +#line 265 shadow_0 = Hamburger4MSM_0(shadowMap_0.Sample(iblSmp_0, shadowUV_0), z_f_1) * (step(0.0f, shadowUV_0.x) * step(shadowUV_0.x, 1.0f) * step(0.0f, shadowUV_0.y) * step(shadowUV_0.y, 1.0f) * step(0.0f, z_f_1) * step(z_f_1, 1.0f)); -#line 246 +#line 247 } else { -#line 246 +#line 247 shadow_0 = 0.0f; -#line 246 +#line 247 } -#line 246 +#line 247 int l_0 = int(0); -#line 246 +#line 247 float3 resultColor_0 = _S8; -#line 286 +#line 287 for(;;) { -#line 286 +#line 287 if(l_0 < (pushConstants_0.activeDirectionalLights_0)) { } else { -#line 286 +#line 287 break; } float3 resultColor_1 = resultColor_0 + PBR_0(_S9, directionalLightList_0.lights_0[l_0].lightDirection_0, directionalLightList_0.lights_0[l_0].lightColor_0 * directionalLightList_0.lights_0[l_0].intensity_0, l_0) * (1.0f - shadow_0); -#line 286 +#line 287 l_0 = l_0 + int(1); -#line 286 +#line 287 resultColor_0 = resultColor_1; -#line 286 +#line 287 } -#line 295 +#line 296 float3 F_1 = Froughness_0(F0_4, V_5, N_5, roughness_2); -#line 309 +#line 310 float2 brdf_0 = brdfLUT_0.Sample(iblSmp_0, float2(max(dot(N_5, V_5), 0.0f), roughness_2)).xy; -#line 331 - return float4((1.0f - metallic_0) * ((float3)1.0f - F_1) * (irradianceMap_0.Sample(iblSmp_0, N_5).xyz * albedo_2) + prefilterMap_0.SampleLevel(iblSmp_0, reflect(- V_5, N_5), roughness_2 * 4.0f).xyz * (F_1 * brdf_0.x + brdf_0.y) + resultColor_0, 1.0f); +#line 332 + return float4(((1.0f - metallic_0) * ((float3)1.0f - F_1) * (irradianceMap_0.Sample(iblSmp_0, N_5).xyz * albedo_2) + prefilterMap_0.SampleLevel(iblSmp_0, reflect(- V_5, N_5), roughness_2 * 4.0f).xyz * (F_1 * brdf_0.x + brdf_0.y)) * SSAO_0.Sample(gSampler_0, _S7.uv_0).x + resultColor_0, 1.0f); } diff --git a/Engine/shaders/slang/GlobalLightingPass.slang b/Engine/shaders/slang/GlobalLightingPass.slang index e0676df2..b917c994 100644 --- a/Engine/shaders/slang/GlobalLightingPass.slang +++ b/Engine/shaders/slang/GlobalLightingPass.slang @@ -66,6 +66,7 @@ Texture2D gAlbedo : register(t0, space1); Texture2D gNormal : register(t1, space1); Texture2D gPosition : register(t2, space1); Texture2D gMaterial : register(t3, space1); +Texture2D SSAO : register(t4, space1); SamplerState gSampler : register(s0, space1); #if defined(__hlsl__) @@ -313,8 +314,8 @@ float4 fragmentMain(VSOutput input) : SV_Target #endif float3 specular = prefilteredColor * (F * brdf.x + brdf.y); - // 1.0 == ao - float3 ambient = (Kd * diffuse + specular) * 1.0; + float ao = SSAO.Sample(gSampler, input.uv).r; + float3 ambient = (Kd * diffuse + specular) * ao; resultColor = ambient + resultColor; // Blinn-Phong Result Color diff --git a/Engine/shaders/spirv/GlobalLightingPass.frag.spv b/Engine/shaders/spirv/GlobalLightingPass.frag.spv index 602804d59441a30d5ba26a49cd6ceaa5253e0d5a..12733a8305af87e83c7937d7e9b0112e8e436049 100644 GIT binary patch literal 11248 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 G2K^56-oVrV literal 11000 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 KznSgBq5lDC6QvIT diff --git a/Engine/source/DXGlobalLightingContext.cpp b/Engine/source/DXGlobalLightingContext.cpp index f1310d45..855599aa 100644 --- a/Engine/source/DXGlobalLightingContext.cpp +++ b/Engine/source/DXGlobalLightingContext.cpp @@ -19,9 +19,10 @@ void DXGlobalLightingContext::Initialize() // Create root signature and pipeline // The slot of a root signature version 1.1 std::vector rootParameters; - rootParameters.resize(5); + rootParameters.resize(6); rootParameters[0].InitAsConstantBufferView(0, 0, D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC, D3D12_SHADER_VISIBILITY_PIXEL); rootParameters[1].InitAsConstants(sizeof(PushConstants) / 4, 1, 0, D3D12_SHADER_VISIBILITY_PIXEL); + // G-Buffer SRVs: Albedo, Normal, Depth, Material CD3DX12_DESCRIPTOR_RANGE1 gBufferSrvRange; gBufferSrvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 0, 1); rootParameters[2].InitAsDescriptorTable(1, &gBufferSrvRange, D3D12_SHADER_VISIBILITY_PIXEL); @@ -31,6 +32,9 @@ void DXGlobalLightingContext::Initialize() CD3DX12_DESCRIPTOR_RANGE1 shadowMapRange; shadowMapRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 3, 2); rootParameters[4].InitAsDescriptorTable(1, &shadowMapRange, D3D12_SHADER_VISIBILITY_PIXEL); + CD3DX12_DESCRIPTOR_RANGE1 ssaoRange; + ssaoRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 4, 1); + rootParameters[5].InitAsDescriptorTable(1, &ssaoRange, D3D12_SHADER_VISIBILITY_PIXEL); m_renderManager->CreateRootSignature(m_rootSignature, rootParameters); DXHelper::ThrowIfFailed(m_rootSignature->SetName(L"Global Lighting-Pass Root Signature")); @@ -110,6 +114,10 @@ void DXGlobalLightingContext::Execute(ICommandListWrapper* commandListWrapper) shadowGpuHandle.ptr += static_cast(shadowSrvIndex) * m_renderManager->m_srvDescriptorSize; commandList->SetGraphicsRootDescriptorTable(4, shadowGpuHandle); + D3D12_GPU_DESCRIPTOR_HANDLE ssaoGpuHandle = m_renderManager->m_srvHeap->GetGPUDescriptorHandleForHeapStart(); + ssaoGpuHandle.ptr += static_cast(m_renderManager->GetSSAOContext()->GetBlurredAOSrvIndex()) * m_renderManager->m_srvDescriptorSize; + commandList->SetGraphicsRootDescriptorTable(5, ssaoGpuHandle); + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); commandList->DrawInstanced(3, 1, 0, 0); diff --git a/Engine/source/DXRenderManager.cpp b/Engine/source/DXRenderManager.cpp index db382451..6c29b211 100644 --- a/Engine/source/DXRenderManager.cpp +++ b/Engine/source/DXRenderManager.cpp @@ -221,6 +221,10 @@ void DXRenderManager::Initialize(SDL_Window* window) m_gBufferContext = std::make_unique(this); m_gBufferContext->Initialize(); + // Create SSAO Context + m_ssaoContext = std::make_unique(this); + m_ssaoContext->Initialize(); + // Create Naive Render Context m_naiveLightingContext = std::make_unique(this); m_naiveLightingContext->Initialize(); @@ -352,6 +356,7 @@ void DXRenderManager::OnResize() if (m_deferredRenderingEnabled) { m_gBufferContext->OnResize(); + m_ssaoContext->OnResize(); m_globalLightingContext->OnResize(); m_localLightingContext->OnResize(); m_naiveLightingContext->OnResize(); @@ -431,6 +436,7 @@ bool DXRenderManager::BeginRender(glm::vec3 bgColor) m_shadowMapContext->Execute(&wrapper); m_gBufferContext->Execute(&wrapper); + m_ssaoContext->Execute(&wrapper); //m_naiveLightingContext->Execute(&wrapper); m_globalLightingContext->Execute(&wrapper); if (!m_meshletVisualization) m_localLightingContext->Execute(&wrapper); diff --git a/Engine/source/DXSSAOContext.cpp b/Engine/source/DXSSAOContext.cpp index fc82abb1..eee14972 100644 --- a/Engine/source/DXSSAOContext.cpp +++ b/Engine/source/DXSSAOContext.cpp @@ -24,7 +24,7 @@ void DXSSAOContext::Initialize() std::vector rootParameters(2); rootParameters[0].InitAsConstants(sizeof(PushConstants) / 4, 0, 0, D3D12_SHADER_VISIBILITY_PIXEL);; CD3DX12_DESCRIPTOR_RANGE1 gBufferRange; - gBufferRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 0, 0); + gBufferRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 0, 1); rootParameters[1].InitAsDescriptorTable(1, &gBufferRange, D3D12_SHADER_VISIBILITY_PIXEL); m_renderManager->CreateRootSignature(m_ssaoRootSignature, rootParameters); @@ -45,7 +45,7 @@ void DXSSAOContext::Initialize() rootParameters[0].InitAsConstants(sizeof(PushConstants) / 4, 0, 0, D3D12_SHADER_VISIBILITY_PIXEL);; rootParameters[1].InitAsDescriptorTable(1, &gBufferRange, D3D12_SHADER_VISIBILITY_PIXEL); CD3DX12_DESCRIPTOR_RANGE1 ssaoRange; - ssaoRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 4, 0); + ssaoRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 4, 1); rootParameters[2].InitAsDescriptorTable(1, &ssaoRange, D3D12_SHADER_VISIBILITY_PIXEL); m_renderManager->CreateRootSignature(m_blurRootSignature, rootParameters); @@ -165,6 +165,9 @@ void DXSSAOContext::CreateSSAOResources() D3D12_CLEAR_VALUE clearValue = {}; clearValue.Format = DXGI_FORMAT_R8_UNORM; clearValue.Color[0] = 1.0f; + clearValue.Color[1] = 1.0f; + clearValue.Color[2] = 1.0f; + clearValue.Color[3] = 1.0f; CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( @@ -211,6 +214,9 @@ void DXSSAOContext::CreateBlurResources() D3D12_CLEAR_VALUE clearValue = {}; clearValue.Format = DXGI_FORMAT_R8_UNORM; clearValue.Color[0] = 1.0f; + clearValue.Color[1] = 1.0f; + clearValue.Color[2] = 1.0f; + clearValue.Color[3] = 1.0f; CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( From 7663a082b93492b5e7c778ab7b2bb0c867687bad Mon Sep 17 00:00:00 2001 From: rapt0r Date: Fri, 3 Apr 2026 23:26:17 -0700 Subject: [PATCH 05/18] Horizontal & Vertical Blur Pass --- Engine/include/DXRenderManager.hpp | 2 +- Engine/include/DXSSAOContext.hpp | 6 ++ Engine/shaders/hlsl/SSAO.frag.hlsl | 35 ++++++----- Engine/shaders/hlsl/SSAOBlur.frag.hlsl | 76 ++++++++-------------- Engine/shaders/slang/SSAO.slang | 1 + Engine/shaders/slang/SSAOBlur.slang | 34 +++++----- Engine/shaders/spirv/SSAO.frag.spv | Bin 6012 -> 6064 bytes Engine/shaders/spirv/SSAOBlur.frag.spv | Bin 6036 -> 5704 bytes Engine/source/DXSSAOContext.cpp | 84 ++++++++++++++++++++++--- Engine/source/RenderManager.cpp | 4 ++ 10 files changed, 148 insertions(+), 94 deletions(-) diff --git a/Engine/include/DXRenderManager.hpp b/Engine/include/DXRenderManager.hpp index 7a351f58..6597a470 100644 --- a/Engine/include/DXRenderManager.hpp +++ b/Engine/include/DXRenderManager.hpp @@ -67,6 +67,7 @@ class DXRenderManager : public RenderManager DXShadowMapContext* GetShadowMapContext() const { return m_shadowMapContext.get(); } DXPostProcessContext* GetPostProcessContext() const { return m_postProcessContext.get(); } + DXSSAOContext* GetSSAOContext() const { return m_ssaoContext.get(); } private: int m_width, m_height; bool m_isResize{ false }; @@ -135,7 +136,6 @@ class DXRenderManager : public RenderManager std::unique_ptr m_gBufferContext; DXGBufferContext* GetGBufferContext() const { return m_gBufferContext.get(); } std::unique_ptr m_ssaoContext; - DXSSAOContext* GetSSAOContext() const { return m_ssaoContext.get(); } // Naive Lighting Context std::unique_ptr m_naiveLightingContext; // Global (Directional) Lighting Context diff --git a/Engine/include/DXSSAOContext.hpp b/Engine/include/DXSSAOContext.hpp index e5e7b360..4c5466d5 100644 --- a/Engine/include/DXSSAOContext.hpp +++ b/Engine/include/DXSSAOContext.hpp @@ -37,6 +37,11 @@ class DXSSAOContext : public IRenderContext ComPtr m_blurTexture; // R8_UNORM ComPtr m_blurRtvHeap; std::pair m_blurSrvHandle; + + ComPtr m_blurIntermediateTexture; + ComPtr m_blurIntermediateRtvHeap; + std::pair m_blurIntermediateSrvHandle; + ComPtr m_blurRootSignature; std::unique_ptr m_blurPipeline; @@ -47,6 +52,7 @@ class DXSSAOContext : public IRenderContext { glm::mat4 view; glm::mat4 projection; + glm::ivec2 blurDirection; float radius; float scale; float contrast; diff --git a/Engine/shaders/hlsl/SSAO.frag.hlsl b/Engine/shaders/hlsl/SSAO.frag.hlsl index ffa6ba88..d4514837 100644 --- a/Engine/shaders/hlsl/SSAO.frag.hlsl +++ b/Engine/shaders/hlsl/SSAO.frag.hlsl @@ -9,13 +9,13 @@ #endif -#line 42 "slang/SSAO.slang" +#line 43 "slang/SSAO.slang" Texture2D gPosition_0 : register(t2, space1); SamplerState gSampler_0 : register(s0, space1); -#line 41 +#line 42 Texture2D gNormal_0 : register(t1, space1); @@ -24,6 +24,7 @@ struct PushConstants_0 { float4x4 view_0; float4x4 projection_0; + int2 blurDirection_0; float radius_0; float scale_0; float contrast_0; @@ -46,11 +47,11 @@ struct VSOutput_0 }; -#line 47 +#line 48 float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET { -#line 47 +#line 48 VSOutput_0 _S1 = input_0; float3 P_0 = gPosition_0.SampleLevel(gSampler_0, input_0.uv_0, 0.0f).xyz; @@ -59,7 +60,7 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET if((length(N_0)) < 0.10000000149011612f) { -#line 52 +#line 53 return (float4)1.0f; } @@ -68,55 +69,55 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET int2 _S3 = int2(_S1.position_0.xy); int _S4 = _S3.x; -#line 58 +#line 59 int _S5 = _S3.y; -#line 58 +#line 59 float _S6 = float(((int(30) * _S4) ^ _S5) + int(10) * _S4 * _S5); float c_0 = 0.10000000149011612f * pushConstants_0.radius_0; -#line 61 +#line 62 int i_0 = int(0); -#line 61 +#line 62 float S_0 = 0.0f; for(;;) { -#line 63 +#line 64 if(i_0 < (pushConstants_0.numSamples_0)) { } else { -#line 63 +#line 64 break; } float alpha_0 = (float(i_0) + 0.5f) / float(pushConstants_0.numSamples_0); float theta_0 = 6.28318548202514648f * alpha_0 * (7.0f * float(pushConstants_0.numSamples_0) / 9.0f) + _S6; -#line 72 +#line 73 float3 Pi_0 = gPosition_0.SampleLevel(gSampler_0, _S1.uv_0 + alpha_0 * pushConstants_0.radius_0 / _S2 * float2(cos(theta_0), sin(theta_0)) * float2(pushConstants_0.projection_0[int(1)][int(1)] / pushConstants_0.projection_0[int(0)][int(0)], 1.0f) * 0.5f, 0.0f).xyz; float3 wi_0 = Pi_0 - P_0; -#line 80 +#line 81 float S_1 = S_0 + max(0.0f, dot(N_0, wi_0) - pushConstants_0.delta_0 * mul(pushConstants_0.view_0, float4(Pi_0, 1.0f)).z) * step(length(wi_0), pushConstants_0.radius_0) / max(c_0 * c_0, dot(wi_0, wi_0)); -#line 63 +#line 64 i_0 = i_0 + int(1); -#line 63 +#line 64 S_0 = S_1; -#line 63 +#line 64 } -#line 85 +#line 86 return (float4)pow(max(0.0f, 1.0f - pushConstants_0.scale_0 * (S_0 * (6.28318548202514648f * c_0 / float(pushConstants_0.numSamples_0)))), pushConstants_0.contrast_0); } diff --git a/Engine/shaders/hlsl/SSAOBlur.frag.hlsl b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl index 8ca86be6..2ca595fb 100644 --- a/Engine/shaders/hlsl/SSAOBlur.frag.hlsl +++ b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl @@ -14,6 +14,7 @@ struct PushConstants_0 { float4x4 view_0; float4x4 projection_0; + int2 blurDirection_0; float radius_0; float scale_0; float contrast_0; @@ -36,7 +37,7 @@ Texture2D gNormal_0 : register(t1, space1); SamplerState gSampler_0 : register(s0, space1); -#line 29 +#line 30 Texture2D gPosition_0 : register(t2, space1); Texture2D SSAO_0 : register(t4, space1); @@ -50,11 +51,11 @@ struct VSOutput_0 }; -#line 35 +#line 36 float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET { -#line 35 +#line 36 VSOutput_0 _S1 = input_0; float2 _S2 = 1.0f / float2(pushConstants_0.screenWidth_0, pushConstants_0.screenHeight_0); @@ -62,83 +63,60 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET if((length(centerN_0)) < 0.10000000149011612f) { -#line 39 +#line 40 return (float4)1.0f; } float _S3 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, _S1.uv_0, 0.0f).xyz, 1.0f)).z; -#line 42 - int x_0 = int(-2); +#line 43 + int i_0 = int(-2); -#line 42 +#line 43 float result_0 = 0.0f; -#line 42 +#line 43 float weightSum_0 = 0.0f; -#line 48 +#line 49 for(;;) { -#line 48 - if(x_0 <= int(2)) +#line 49 + if(i_0 <= int(2)) { } else { -#line 48 +#line 49 break; } -#line 48 - int y_0 = int(-2); + float2 sampleUV_0 = _S1.uv_0 + float2(float(pushConstants_0.blurDirection_0.x * i_0), float(pushConstants_0.blurDirection_0.y * i_0)) * _S2; - for(;;) - { - -#line 50 - if(y_0 <= int(2)) - { - } - else - { - -#line 50 - break; - } - - float2 sampleUV_0 = _S1.uv_0 + float2(float(x_0), float(y_0)) * _S2; +#line 62 + float depthDiff_0 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, 1.0f)).z - _S3; -#line 63 - float depthDiff_0 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, 1.0f)).z - _S3; -#line 68 - float weight_0 = exp(float(- (x_0 * x_0 + y_0 * y_0)) / 8.0f) * (max(0.0f, dot(gNormal_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, centerN_0)) * (1.0f / sqrt(0.06283184140920639f) * exp(- (depthDiff_0 * depthDiff_0) / 0.01999999955296516f))); + float weight_0 = exp(float(- (i_0 * i_0)) / 8.0f) * max(0.0f, dot(gNormal_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, centerN_0)) * (1.0f / sqrt(0.06283184140920639f) * exp(- (depthDiff_0 * depthDiff_0) / 0.01999999955296516f)); - float result_1 = result_0 + SSAO_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).x * weight_0; - float weightSum_1 = weightSum_0 + weight_0; + float result_1 = result_0 + SSAO_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).x * weight_0; + float weightSum_1 = weightSum_0 + weight_0; -#line 50 - y_0 = y_0 + int(1); +#line 49 + i_0 = i_0 + int(1); -#line 50 - result_0 = result_1; - -#line 50 - weightSum_0 = weightSum_1; - -#line 50 - } +#line 49 + result_0 = result_1; -#line 48 - x_0 = x_0 + int(1); +#line 49 + weightSum_0 = weightSum_1; -#line 48 +#line 49 } -#line 75 +#line 71 return (float4)(result_0 / max(weightSum_0, 0.00009999999747379f)); } diff --git a/Engine/shaders/slang/SSAO.slang b/Engine/shaders/slang/SSAO.slang index e5467281..3d0d6971 100644 --- a/Engine/shaders/slang/SSAO.slang +++ b/Engine/shaders/slang/SSAO.slang @@ -23,6 +23,7 @@ struct PushConstants { float4x4 view; float4x4 projection; + int2 blurDirection; float radius; float scale; float contrast; diff --git a/Engine/shaders/slang/SSAOBlur.slang b/Engine/shaders/slang/SSAOBlur.slang index 6c478774..d9878ff3 100644 --- a/Engine/shaders/slang/SSAOBlur.slang +++ b/Engine/shaders/slang/SSAOBlur.slang @@ -10,6 +10,7 @@ struct PushConstants { float4x4 view; float4x4 projection; + int2 blurDirection; float radius; float scale; float contrast; @@ -45,31 +46,26 @@ float4 fragmentMain(VSOutput input) : SV_Target float weightSum = 0.0f; float variance = 0.01f; - for (int x = -2; x <= 2; ++x) + for (int i = -2; i <= 2; ++i) { - for (int y = -2; y <= 2; ++y) - { - float2 offset = float2(x, y) * texelSize; - float2 sampleUV = input.uv + offset; + float2 offset = float2(pushConstants.blurDirection.x * i, pushConstants.blurDirection.y * i) * texelSize; + float2 sampleUV = input.uv + offset; - float sampleAO = SSAO.SampleLevel(gSampler, sampleUV, 0).r; - float3 sampleN = gNormal.SampleLevel(gSampler, sampleUV, 0).xyz; - float3 sampleP = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; - float sampleD = mul(pushConstants.view, float4(sampleP, 1.0f)).z; + float sampleAO = SSAO.SampleLevel(gSampler, sampleUV, 0).r; + float3 sampleN = gNormal.SampleLevel(gSampler, sampleUV, 0).xyz; + float3 sampleP = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; + float sampleD = mul(pushConstants.view, float4(sampleP, 1.0f)).z; - float spatialWeight = exp(-(x * x + y * y) / 8.0f); + float spatialWeight = exp(-(i * i) / 8.0f); - float normalTerm = max(0.0f, dot(sampleN, centerN)); - float depthDiff = sampleD - centerD; - float depthTerm = (1.0f / sqrt(2.0f * 3.141592f * variance)) * exp(-(depthDiff * depthDiff) / (2.0f * variance)); + float normalTerm = max(0.0f, dot(sampleN, centerN)); + float depthDiff = sampleD - centerD; + float depthTerm = (1.0f / sqrt(2.0f * 3.141592f * variance)) * exp(-(depthDiff * depthDiff) / (2.0f * variance)); - float rangeWeight = normalTerm * depthTerm; + float weight = spatialWeight * normalTerm * depthTerm; - float weight = spatialWeight * rangeWeight; - - result += sampleAO * weight; - weightSum += weight; - } + result += sampleAO * weight; + weightSum += weight; } return result / max(weightSum, 0.0001f); diff --git a/Engine/shaders/spirv/SSAO.frag.spv b/Engine/shaders/spirv/SSAO.frag.spv index e885a752549075e5de5cfe34cf75b6f92c79d39a..d47b85fad65b8f8dcaf63aaf3baf9f3bcc2eacf9 100644 GIT binary patch delta 1246 zcmY+EPfrs;7{+I|-EJ!_wkc*Ir2a`mG=dOfj9x0%RzQmaqM{h4nEI1tLr3B=bhjCzVp5_JLysPUeDeyS+Yb<2w^}o zwUv6YT6fFK)#r;?M}+D5La^&jrMj~8kA=aO%1+Jo;v!z0sWOIrAp)|vvM}Z>yr{W> z3=6#C)|Q<>MpQY5-4+8`D%V|ianP;K%`an#$`Mg$>>53WTvz+ywE7;7_nL5Ip&e*Y zH^*{h?*fda$Udl)nLhC`;9)6xJ~cYbDS5^gVUfp@8}kNEinw=@tFWoO+Kps~uESy? z@2L|Rj4nbPr?I|)nSN%pV$BoU5bucbQOp%ch?jjTX?4kv%2}smL`_D;I0qB*t*YnJ&z!A4!_1@*kI@XD>Cs1dhf>%e4<%M zx$z0_3rvIX)_5qkz=#oiYzOlUGzmS0rl4tP1Ye1_T86qIK7<|3T+Ny1SDb}S&Z7=v z-*(J%P^%Csn@Gj-u;cr46%iD$tz|7lf`Rr*YN96i z1(><$(X%m>4K_{*BTp@dIMpH8`9RTgdb$dS#4B28B=cRRx$umuWmTb zTHaZyEw}d?*qv>C(ueiLGo#yB=oBs1XaYJTvcFGe${- zPidicw8xH%wnxo(~ohJ0(LjTeAExo?*G*ztg7wo4r%W{HkuCNOKTv25#oAf;bo4-=e1 zIVb}k_HzXyx8XR7aZ)i1ZDz^e$6|x*@G6ui#>3TQ*B~1>bt65;@GrV9GD>EA$1*$z=3`s7gC}ASPPSg2CO11?(RqPF79+kOn9E1C|p^MNt cC=GFq+tm(Y`do%wAAIq$U?s)2T(Ktq0}YvkBLDyZ diff --git a/Engine/shaders/spirv/SSAOBlur.frag.spv b/Engine/shaders/spirv/SSAOBlur.frag.spv index d06506e066c1e7b85c984e03e73f4e68330d9ca9..99b03ecb0d6375f8166323a036c612d801e812db 100644 GIT binary patch literal 5704 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, &barrier); - // Bilateral Blur Pass - barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + // Bilateral Blur Pass (Horizontal) + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurIntermediateTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); commandList->ResourceBarrier(1, &barrier); commandList->SetPipelineState(m_blurPipeline->GetPipelineState().Get()); commandList->SetGraphicsRootSignature(m_blurRootSignature.Get()); - rtvHandle = m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart(); + rtvHandle = m_blurIntermediateRtvHeap->GetCPUDescriptorHandleForHeapStart(); commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + pushConstants.blurDirection = glm::ivec2(1, 0); commandList->SetGraphicsRoot32BitConstants(0, sizeof(PushConstants) / 4, &pushConstants, 0); commandList->SetGraphicsRootDescriptorTable(1, gBufferGpuHandle); D3D12_GPU_DESCRIPTOR_HANDLE ssaoSrvGpuHandle = m_renderManager->m_srvHeap->GetGPUDescriptorHandleForHeapStart(); @@ -139,6 +140,29 @@ void DXSSAOContext::Execute(ICommandListWrapper* commandListWrapper) commandList->DrawInstanced(3, 1, 0, 0); + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurIntermediateTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + commandList->ResourceBarrier(1, &barrier); + + // Bilateral Blur Pass (Vertical) + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + + commandList->SetPipelineState(m_blurPipeline->GetPipelineState().Get()); + commandList->SetGraphicsRootSignature(m_blurRootSignature.Get()); + + rtvHandle = m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart(); + commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); + commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + + pushConstants.blurDirection = glm::ivec2(0, 1); + commandList->SetGraphicsRoot32BitConstants(0, sizeof(PushConstants) / 4, &pushConstants, 0); + commandList->SetGraphicsRootDescriptorTable(1, gBufferGpuHandle); + D3D12_GPU_DESCRIPTOR_HANDLE intermediateSrvGpuHandle = m_renderManager->m_srvHeap->GetGPUDescriptorHandleForHeapStart(); + intermediateSrvGpuHandle.ptr += static_cast(m_blurIntermediateSrvHandle.second) * m_renderManager->m_srvDescriptorSize; + commandList->SetGraphicsRootDescriptorTable(2, intermediateSrvGpuHandle); + + commandList->DrawInstanced(3, 1, 0, 0); + barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_blurTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); commandList->ResourceBarrier(1, &barrier); } @@ -218,6 +242,7 @@ void DXSSAOContext::CreateBlurResources() clearValue.Color[2] = 1.0f; clearValue.Color[3] = 1.0f; + // 2. Create Intermediate Blur Render Target (Horizontal Pass) CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( &heapProps, @@ -225,22 +250,65 @@ void DXSSAOContext::CreateBlurResources() &textureDesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, &clearValue, - IID_PPV_ARGS(&m_blurTexture) + IID_PPV_ARGS(&m_blurIntermediateTexture) )); - // 2. Create RTV Heap for SSAO Render Target + // Create RTV Heap for SSAO Render Target D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = 1; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_blurIntermediateRtvHeap))); + DXHelper::ThrowIfFailed(m_blurIntermediateRtvHeap->SetName(L"SSAO Intermediate Blur Render Target View Heap")); + + // Create RTV for SSAO Render Target + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_blurIntermediateRtvHeap->GetCPUDescriptorHandleForHeapStart()); + m_renderManager->m_device->CreateRenderTargetView(m_blurIntermediateTexture.Get(), nullptr, rtvHandle); + + // Create SRV in Main SRV Heap + m_blurIntermediateSrvHandle = m_renderManager->AllocateSrvHandles(1); + m_renderManager->m_device->CreateShaderResourceView(m_blurIntermediateTexture.Get(), nullptr, m_blurIntermediateSrvHandle.first); + + // 3. Create Final Blur Render Target (Vertical Pass) + heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + &clearValue, + IID_PPV_ARGS(&m_blurTexture) + )); + + // Create RTV Heap for SSAO Render Target + rtvHeapDesc.NumDescriptors = 1; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; DXHelper::ThrowIfFailed(m_renderManager->m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_blurRtvHeap))); - DXHelper::ThrowIfFailed(m_blurRtvHeap->SetName(L"SSAO Blur Render Target View Heap")); + DXHelper::ThrowIfFailed(m_blurRtvHeap->SetName(L"SSAO Final Blur Render Target View Heap")); - // 3. Create RTV for SSAO Render Target - CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart()); + // Create RTV for SSAO Render Target + rtvHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_blurRtvHeap->GetCPUDescriptorHandleForHeapStart()); m_renderManager->m_device->CreateRenderTargetView(m_blurTexture.Get(), nullptr, rtvHandle); // Create SRV in Main SRV Heap m_blurSrvHandle = m_renderManager->AllocateSrvHandles(1); m_renderManager->m_device->CreateShaderResourceView(m_blurTexture.Get(), nullptr, m_blurSrvHandle.first); } + +void DXSSAOContext::DrawImGui() +{ + if (ImGui::CollapsingHeader("Ambient Occlusion (Alchemy AO)")) + { + ImGui::Checkbox("Enable SSAO", &m_enabled); + + if (m_enabled) + { + ImGui::SliderFloat("Radius", &m_radius, 0.01f, 2.0f, "%.3f"); + ImGui::SliderFloat("Scale", &m_scale, 0.1f, 5.0f, "%.2f"); + ImGui::SliderFloat("Contrast", &m_contrast, 0.1f, 5.0f, "%.2f"); + ImGui::SliderInt("Samples", &m_numSamples, 1, 32); + ImGui::DragFloat("Depth Delta", &m_delta, 0.0001f, 0.0f, 0.05f, "%.4f"); + } + } +} diff --git a/Engine/source/RenderManager.cpp b/Engine/source/RenderManager.cpp index 7e818a64..9640fe96 100644 --- a/Engine/source/RenderManager.cpp +++ b/Engine/source/RenderManager.cpp @@ -1256,9 +1256,13 @@ void RenderManager::RenderingControllerForImGui() if (renderManager->gMode == GraphicsMode::DX) { ImGui::Spacing(); + // Shadow Map Context bool shadowEnabled = dxRenderManager->GetShadowMapContext()->IsEnabled(); if (ImGui::Checkbox("Shadow Map", &shadowEnabled)) dxRenderManager->GetShadowMapContext()->SetEnabled(shadowEnabled); if (shadowEnabled) dxRenderManager->GetShadowMapContext()->DrawImGui(); + + // SSAO Context + dxRenderManager->GetSSAOContext()->DrawImGui(); } ImGui::End(); From 949eaa67d4e057bc38ce5a7861ba3ade8d122116 Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sat, 4 Apr 2026 01:41:41 -0700 Subject: [PATCH 06/18] Minor Code Fix --- Engine/shaders/hlsl/SSAO.frag.hlsl | 8 ++++---- Engine/shaders/slang/SSAO.slang | 3 ++- Engine/shaders/spirv/SSAO.frag.spv | Bin 6064 -> 5800 bytes 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Engine/shaders/hlsl/SSAO.frag.hlsl b/Engine/shaders/hlsl/SSAO.frag.hlsl index d4514837..626f4eba 100644 --- a/Engine/shaders/hlsl/SSAO.frag.hlsl +++ b/Engine/shaders/hlsl/SSAO.frag.hlsl @@ -101,11 +101,11 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET float theta_0 = 6.28318548202514648f * alpha_0 * (7.0f * float(pushConstants_0.numSamples_0) / 9.0f) + _S6; -#line 73 - float3 Pi_0 = gPosition_0.SampleLevel(gSampler_0, _S1.uv_0 + alpha_0 * pushConstants_0.radius_0 / _S2 * float2(cos(theta_0), sin(theta_0)) * float2(pushConstants_0.projection_0[int(1)][int(1)] / pushConstants_0.projection_0[int(0)][int(0)], 1.0f) * 0.5f, 0.0f).xyz; +#line 74 + float3 Pi_0 = gPosition_0.SampleLevel(gSampler_0, _S1.uv_0 + alpha_0 * pushConstants_0.radius_0 / _S2 * float2(cos(theta_0), sin(theta_0)), 0.0f).xyz; float3 wi_0 = Pi_0 - P_0; -#line 81 +#line 82 float S_1 = S_0 + max(0.0f, dot(N_0, wi_0) - pushConstants_0.delta_0 * mul(pushConstants_0.view_0, float4(Pi_0, 1.0f)).z) * step(length(wi_0), pushConstants_0.radius_0) / max(c_0 * c_0, dot(wi_0, wi_0)); #line 64 @@ -117,7 +117,7 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET #line 64 } -#line 86 +#line 87 return (float4)pow(max(0.0f, 1.0f - pushConstants_0.scale_0 * (S_0 * (6.28318548202514648f * c_0 / float(pushConstants_0.numSamples_0)))), pushConstants_0.contrast_0); } diff --git a/Engine/shaders/slang/SSAO.slang b/Engine/shaders/slang/SSAO.slang index 3d0d6971..19610f76 100644 --- a/Engine/shaders/slang/SSAO.slang +++ b/Engine/shaders/slang/SSAO.slang @@ -68,7 +68,8 @@ float4 fragmentMain(VSOutput input) : SV_Target float theta = 2.f * PI * alpha * (7.0f * (float)pushConstants.numSamples / 9.0f) + phi; float2 offset = h * float2(cos(theta), sin(theta)); - float2 sampleUV = input.uv + offset * float2(pushConstants.projection[1][1] / pushConstants.projection[0][0], 1.0f) * 0.5f; + // float2 sampleUV = input.uv + offset * float2(pushConstants.projection[1][1] / pushConstants.projection[0][0], 1.0f) * 0.5f; + float2 sampleUV = input.uv + offset; float3 Pi = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; float3 wi = Pi - P; diff --git a/Engine/shaders/spirv/SSAO.frag.spv b/Engine/shaders/spirv/SSAO.frag.spv index d47b85fad65b8f8dcaf63aaf3baf9f3bcc2eacf9..851b44d7025ca08159080e0674c9e68c789074c6 100644 GIT binary patch delta 1384 zcmYk6%S+Tz6vxlZ&q+s2$|WC)Xuv#P*^!ZNrj`M>r=X<{Q+;h%7bLV!gJX>8HL@V+wh?rTW z{ju)iH9@2^Yzz{Sp0GMnwl2-W{p)* zMbHd3ld}PP$!VC3rqNsm()B4$hrR-&>+{-GxHOH`YuB6>HA`j1>rM<@po-i8Dw4bT zrqeOmy}eG$jq7t7MY3_XoHkP@ZNwN!Q2-T)7qF z53t}HP9f0$USrWqC2b@eoL{y2J4}z%VOI4>jR9$Ttm?T@T9YQOETiH2(zVekOYbeM RiOkarq!&l_FL$>N`~%L=!TtaM delta 1652 zcmY+EOGs2v9LCR`aT-U|AQhp4Bq1czvPj&hm}Of-h-fES5F`W@Zi4AS)TStIt9I?$ zWZLvD3&URaewb-5%O3W!G$A9ye&6k!X}a*u|2yCRdCom|j+C^`&klzQqbBSbV~R|M z*PgvF>~;7x;T*5iFY)phU&gViv3cW$wM`~s!lsLL{dyDdEASS}2jNWtkC5dyWvNaDCe5^AW1!lukK1)Vwitf|I|QO&9>3Bj{H*ld5wSvt$hX6@@pOQ{O61Z_F~688NFi+8gqSKZH@4b~P2m5@dNQ#$V@)JP z*67q7@fwC%hUXZl1=@x*ZJ`}VUurdNBLSqlxXthrR+m<3hdOC>)l%LmpgdPgd8dtu z2M&oY@yuU`*+ZgscNVCa^m?=z*mFR76WC?7^YEiUzI|4^0GECUY`0nmd?t{u($uDz zS&)lhb|9pgLhL0l2dpHi2-^u1BYl;9VY)riJNyH&oW?Gg6hRM%ud_EhsZfH|eNs#* z&{nIkS3wNH>1-w1&7MrQWuxx=7PO-LX0*sok|&YTP}mX*!pC z-)dp2smBAL&M9$m^Uyjl$>c{?OKs9)wUlJ@*lMXwdePLxY1+sWAYG3eun*qLZ3)iR ziT#22--PC=)l{(FzNu&M8$c(d4XA4BM$Y#FeiP`#w4r|bC!H_hw}6gL zJ5ysNHev^WnyR>pC{}k@$NCEBBIxe!x7ur~4`AKq2I10mf|+JY@QUMaSX6)|KsU;L zG;iTsKqdp|2;Tw4Eda`q|De4m@8RV@`T9EbC4K<4Ud@w43}R6I_)dG#lj8wjkN|8+@?m%@_&Vuq#*Y1)_AAZ^s|$t^DX0gHldcq7 Date: Sat, 4 Apr 2026 01:50:26 -0700 Subject: [PATCH 07/18] Use abs for Right-Handed Coordinate --- Engine/shaders/hlsl/SSAO.frag.hlsl | 30 +++++++++++++++-------------- Engine/shaders/slang/SSAO.slang | 7 +++++-- Engine/shaders/spirv/SSAO.frag.spv | Bin 5800 -> 5836 bytes 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Engine/shaders/hlsl/SSAO.frag.hlsl b/Engine/shaders/hlsl/SSAO.frag.hlsl index 626f4eba..e2917783 100644 --- a/Engine/shaders/hlsl/SSAO.frag.hlsl +++ b/Engine/shaders/hlsl/SSAO.frag.hlsl @@ -64,60 +64,62 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET return (float4)1.0f; } - float _S2 = mul(pushConstants_0.view_0, float4(P_0, 1.0f)).z; + + + float _S2 = abs(mul(pushConstants_0.view_0, float4(P_0, 1.0f)).z); int2 _S3 = int2(_S1.position_0.xy); int _S4 = _S3.x; -#line 59 +#line 61 int _S5 = _S3.y; -#line 59 +#line 61 float _S6 = float(((int(30) * _S4) ^ _S5) + int(10) * _S4 * _S5); float c_0 = 0.10000000149011612f * pushConstants_0.radius_0; -#line 62 +#line 64 int i_0 = int(0); -#line 62 +#line 64 float S_0 = 0.0f; for(;;) { -#line 64 +#line 66 if(i_0 < (pushConstants_0.numSamples_0)) { } else { -#line 64 +#line 66 break; } float alpha_0 = (float(i_0) + 0.5f) / float(pushConstants_0.numSamples_0); float theta_0 = 6.28318548202514648f * alpha_0 * (7.0f * float(pushConstants_0.numSamples_0) / 9.0f) + _S6; -#line 74 +#line 76 float3 Pi_0 = gPosition_0.SampleLevel(gSampler_0, _S1.uv_0 + alpha_0 * pushConstants_0.radius_0 / _S2 * float2(cos(theta_0), sin(theta_0)), 0.0f).xyz; float3 wi_0 = Pi_0 - P_0; -#line 82 - float S_1 = S_0 + max(0.0f, dot(N_0, wi_0) - pushConstants_0.delta_0 * mul(pushConstants_0.view_0, float4(Pi_0, 1.0f)).z) * step(length(wi_0), pushConstants_0.radius_0) / max(c_0 * c_0, dot(wi_0, wi_0)); +#line 85 + float S_1 = S_0 + max(0.0f, dot(N_0, wi_0) - pushConstants_0.delta_0 * abs(mul(pushConstants_0.view_0, float4(Pi_0, 1.0f)).z)) * step(length(wi_0), pushConstants_0.radius_0) / max(c_0 * c_0, dot(wi_0, wi_0)); -#line 64 +#line 66 i_0 = i_0 + int(1); -#line 64 +#line 66 S_0 = S_1; -#line 64 +#line 66 } -#line 87 +#line 90 return (float4)pow(max(0.0f, 1.0f - pushConstants_0.scale_0 * (S_0 * (6.28318548202514648f * c_0 / float(pushConstants_0.numSamples_0)))), pushConstants_0.contrast_0); } diff --git a/Engine/shaders/slang/SSAO.slang b/Engine/shaders/slang/SSAO.slang index 19610f76..38b2f0b9 100644 --- a/Engine/shaders/slang/SSAO.slang +++ b/Engine/shaders/slang/SSAO.slang @@ -53,7 +53,9 @@ float4 fragmentMain(VSOutput input) : SV_Target if (length(N) < 0.1f) return 1.0f; float4 viewPosition = mul(pushConstants.view, float4(P, 1.0f)); - float d = viewPosition.z; + // Currently Engine uses right-handed system on DirectX + // Use abs to handle right-handed coordinate system where viewPosition.z is negative + float d = abs(viewPosition.z); int2 coord = int2(input.position.xy); float phi = (float)(((30 * coord.x) ^ coord.y) + 10 * coord.x * coord.y); @@ -73,7 +75,8 @@ float4 fragmentMain(VSOutput input) : SV_Target float3 Pi = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; float3 wi = Pi - P; - float di = mul(pushConstants.view, float4(Pi, 1.0f)).z; + // Use abs to handle both left-handed and right-handed coordinate systems + float di = abs(mul(pushConstants.view, float4(Pi, 1.0f)).z); float heaviside = step(length(wi), pushConstants.radius); float numerator = max(0.0f, dot(N, wi) - pushConstants.delta * di) * heaviside; diff --git a/Engine/shaders/spirv/SSAO.frag.spv b/Engine/shaders/spirv/SSAO.frag.spv index 851b44d7025ca08159080e0674c9e68c789074c6..8626e84335135fb57eca385517abb2a8c4ac9a37 100644 GIT binary patch literal 5836 zcmZved2roT6~}*VmO_cNm8GSvC2gfsti(Evwc6=MswvviV5Q(19?5I-YLXY)&<;{5&m!n#idin&*%5YCJ zd(XZ1_tG+b>5QypT9#$Yv;XqHV@@_blQ}7C&(AlaS_aLzk;Ok3JJ_N8+dSwme^DbZorQHNF=& zIoh%%$lZO_dZkgRT3l|K+>X-7*l@Xq3e%pQjjZR?;CUmZ-Q_0Vn!RL-C$1&y!tMiY z?CRyn-RDSx2@W*}tvSs8uF*G^#Z!_wO36mKxm? z-Tgh);ccZo)f%nsUPWiynPI$Ru+%6i+vx8)WZ!swsHZwwZI1cMdGw;nU}K0J&Gnr)$!{rFb`RzG zJ;NUOv0@*vJ+leqK+>;4Ht){N{2rEB;=B5)mC;6Dsa6{4-^CG(KyFKS)pNd;Ii=yT zAscSK+mJ)K-kRNxYz&q2bsKvJc6HaTdYM&u*Y3n_-m43DqQbOicTaN9y=(VO@p+wl zvHN%c*1QjWU#_=hPoUGoa;?OTLD&BzvbnF8>?w3Y^ID$e|L>`nb^88%YqNm1Z&5h3 zeK(7N^TU>#mTcdUeusYTqTjcnKjO8E{tejPh1p;WD~)@-6x-3up5iX*S9gRzIP=SG z1i?*D+<^kulDLBf&U@?JYYUwBR_;)NbDeTG6gcmz+)V|}`zm)!fjcpAhmrQlZ(sEJ z6uRsB7qizEr21*ZxQ5PTcVb)Ldh(|eX`Rj-t(p1t$;~BpZqnVGbI(AUS6=@Dq_Or$ z|BI0N<CKeIA?KF&12^i<(}owO1$<0*0~&Mz7_b)xdJ#`$2mwj_kAik zUWJUfwdju?IkHaMJ#Pf=XCeQ4Z`{j9u!z~-nYdRq^jR-pTkC$-SgMKAF1E9>o@L7aCFuq8zcVutL;5Y72WetfphG%X{H4=fAL8k=Ba$WgoO%gJ-1uPokee zI*y@R^Y6g<%5}usr+L7BXfHr61olJQH_!>}hxStBi-G;v$=a49&jy`9{^Hbo|MrkK zmuvU^Z0FQ{JN_M_UpQiak^g0I=8yU-(d~ECTZJxXT-57Emw&!`tKszvN7U<}d-nR3 zz`q4OM`Q12U%u&A1AS|Oz4SN7@gMr2?{pw%Kh@V07;2=4Xha_%v>t%>s-g4>oj?~|N0{JYK? z#kt!PkC>d>m$+iw1&J%xcthffHFm&RqZs!_YuwU-S zdf~eS-E*;T?#sIRO2|urHO*~~OF&;bw*hqD)F3#NxH7uD^J2fd(B<7*-2L6?-u+gf ze>?U31`L6D35dK$qeN{&uK@k#ZA0!!9D;9plY0lczaRP{ZUo)A_WR)!H;QhozL;A@ z9|O(}?w#oJ#vMp={rl1RO<(gjrH(D{dmBgY1wEhvd~e=`eL(&yVzeiKZ(QCt?6=eR zsXi0A0{EUgkiKW-v*enCJPkPXzW}LUseN*?mD;nCt#p0+k(UG4cNuVf_Ve99KJ53P zyQaJF`dvBzm?bNM9tmB84j|0(oh{ZC`d z#hlNe%N;LppG7y9zS!IC=!1>hY0*CpH|`#EdGq;(y_fNudM~&;@k%kkC>eM&BPVs9!y-Z#zToK*7z2jHHvZH#+G-)`W{A?E7tf<;)-*>o48_) zN8qdxoOl0wK;98GzKMJ3C0<39na~K=HJ3mGDP7Q+i-T4{1yz^qeKS!5$Z}Fyn zf$m#t1^R>kW#Z38dS~Ms@+a8Qt8*#QOh&J`=<@?MZYwWBulzg7llO)IK%YN^`U!{|aV+_)UE(aZe-T zw@@yA3$0-;fA`F-)b2?39AxbK3iN&87>IgTp4n59c1-da&=McJet_M-)L+J7` l|HJ6cpAXEXKi=9$(DfH#Z*PRtXD^>Y+FRvuz7lJ|{{Z&dD**ri literal 5800 zcmZveeUQ~<6~}+F?5aqDDS|+_Kr$G)*{~7i0E?=?ai{VS9>8V?Zuh&k7lfDhCpc;Y&;9_#_o z$*!J{+_|;h7%PqDIaW@^J|#!*6rblj`Y`S%~q+_Y7WMX_8k3=-POt- zWf%YC?DKe|zN<3SZcY~+m-jrb9Gz%vs5Zit*VgCBHcI8{L~|;)=i3}AjoP%x-HAR_ zueBPbW(#$a??SIljJ3O8$l+O+E2H_QBF9N^&7nr6QoF2LZjF$my}pwt`AwDT&XGL7 zXV?!vUhD(5XXd7dl70Z$zB@DWdstzKZy2aoYpsD&qck=+%n^)1Zb^65bH0T+rP1*b z8*aWM$dO#1p52OUja2e=8+#jeeR#N8VO8F>+p*jC>e3ykFkRUlliXA9+MQE;Ugs|C z0Um%g??&H~^as()x!##Qj7~o*jS{y9-PlKw?LBs6kD(Kq*Y#Zge}5ZUvv1LNHw$R{ zE`>weH?$ZyKWsVgkGAhgza#9T-*=)v;7#l6(8?g)Qy z=9lXO!A(otz5>^gIPXHld54{QLxJ-S%N;6ku2b%Cf%ERl-B{qfyK*-dxRVoi1Zkhl z5q&nw)(aRH zy3+Muh_s*1i`pB|9r|B_)Nj6d*d?TEac!~oGJ2NnTNm@M!de8vuA}?=6*iy4ya(pz z^O5IwJ>kCw-SgLfZSuQz{l@JF56!y2FX9hk>o@-WNc-y=BmO3I#^m~rVR(OH{^RH; zfak(G?=QeT6>$N%y;puijMerYxzDf{qb~st{pTQ;E7r-`@8F`>XBReJift zH}N-QH*mOC?Z4;N)ZU)N-g~S&-|kxnk>`SLAb)x4 zy?=+uo6EKPeztMyzMUSRUpQiak^gyc=8yXPDUtU(>aE0zZmHAP1{R7i3|-DW2DdqJo-eI?|Tz?$YZ#}!~8o!bz)Z>kIqC9Z-l@4VRWFuJ^Z+eTjB z`c5z}0g?Bj#=TsRJ_7VRzY|$a93s0eal6p30{S9u6y3S@^}ZB0hHk9Bm|H`y1Lp=e zjxKN9zBKps=+4(yXKkKm1IYWXTF42|51PPtWz23Me?2kUdw_3Q-nZ&E(s!sn1GxhD zZf7EWx5|Hz>onvX;L!gJq<*FLsmWGq&q}t^^<9hH3tZnd!1dYBHv;*v--Pa(K9AS$ z&zpgqaejZEiFEk=(WgBdxE7_gU8}af$om0w^G5G(M3;L@>dObwKbW}N5`P3~E#qzn3xPiO zaW?X^U`eu>*W*!X?0|260b$3WzKDDm-)_zkw4>+*eA z=eNLo`l9yl(5<~3_|}Yx91o-GcYVP`FO~o0Yp@#p53|uI5dZ)H From e44ec0fe2a562b400ae1196f7964f2a01cf9bf9c Mon Sep 17 00:00:00 2001 From: rapt0r Date: Thu, 9 Apr 2026 12:13:43 -0700 Subject: [PATCH 08/18] Minor Code Fix --- Engine/shaders/slang/SSAO.slang | 4 ++-- Engine/shaders/spirv/SSAO.frag.spv | Bin 5836 -> 5820 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/shaders/slang/SSAO.slang b/Engine/shaders/slang/SSAO.slang index 38b2f0b9..31ddbd60 100644 --- a/Engine/shaders/slang/SSAO.slang +++ b/Engine/shaders/slang/SSAO.slang @@ -69,9 +69,9 @@ float4 fragmentMain(VSOutput input) : SV_Target float h = alpha * pushConstants.radius / d; float theta = 2.f * PI * alpha * (7.0f * (float)pushConstants.numSamples / 9.0f) + phi; - float2 offset = h * float2(cos(theta), sin(theta)); + // float2 offset = h * float2(cos(theta), sin(theta)); // float2 sampleUV = input.uv + offset * float2(pushConstants.projection[1][1] / pushConstants.projection[0][0], 1.0f) * 0.5f; - float2 sampleUV = input.uv + offset; + float2 sampleUV = input.uv + h * float2(cos(theta), sin(theta)); float3 Pi = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; float3 wi = Pi - P; diff --git a/Engine/shaders/spirv/SSAO.frag.spv b/Engine/shaders/spirv/SSAO.frag.spv index 8626e84335135fb57eca385517abb2a8c4ac9a37..f63f845531b7b4889a4e112d522bd8c8bed463b7 100644 GIT binary patch delta 12 TcmX@3yGM6}9`j~9=00HnAo~Pa delta 25 gcmdm^dq#JI9y1RM!#V~AhWxa&;?$DOTFjG#0cAf2jsO4v From a5fbfe958647ccc933d831014827fedd1790ff99 Mon Sep 17 00:00:00 2001 From: rapt0r Date: Thu, 9 Apr 2026 13:39:24 -0700 Subject: [PATCH 09/18] Minor Code Fix --- Engine/shaders/hlsl/SSAOBlur.frag.hlsl | 26 ++++++++++++------------- Engine/shaders/slang/SSAOBlur.slang | 11 +++++++---- Engine/shaders/spirv/SSAOBlur.frag.spv | Bin 5704 -> 5676 bytes 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Engine/shaders/hlsl/SSAOBlur.frag.hlsl b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl index 2ca595fb..0d9ca43f 100644 --- a/Engine/shaders/hlsl/SSAOBlur.frag.hlsl +++ b/Engine/shaders/hlsl/SSAOBlur.frag.hlsl @@ -70,7 +70,7 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET float _S3 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, _S1.uv_0, 0.0f).xyz, 1.0f)).z; #line 43 - int i_0 = int(-2); + int i_0 = int(-6); #line 43 float result_0 = 0.0f; @@ -78,45 +78,45 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET #line 43 float weightSum_0 = 0.0f; -#line 49 +#line 52 for(;;) { -#line 49 - if(i_0 <= int(2)) +#line 52 + if(i_0 <= int(6)) { } else { -#line 49 +#line 52 break; } float2 sampleUV_0 = _S1.uv_0 + float2(float(pushConstants_0.blurDirection_0.x * i_0), float(pushConstants_0.blurDirection_0.y * i_0)) * _S2; -#line 62 +#line 65 float depthDiff_0 = mul(pushConstants_0.view_0, float4(gPosition_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, 1.0f)).z - _S3; - float weight_0 = exp(float(- (i_0 * i_0)) / 8.0f) * max(0.0f, dot(gNormal_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, centerN_0)) * (1.0f / sqrt(0.06283184140920639f) * exp(- (depthDiff_0 * depthDiff_0) / 0.01999999955296516f)); + float weight_0 = exp(float(- (i_0 * i_0)) / 18.0f) * max(0.0f, dot(gNormal_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).xyz, centerN_0)) * (1.0f / sqrt(0.06283185631036758f) * exp(- (depthDiff_0 * depthDiff_0) / 0.01999999955296516f)); float result_1 = result_0 + SSAO_0.SampleLevel(gSampler_0, sampleUV_0, 0.0f).x * weight_0; float weightSum_1 = weightSum_0 + weight_0; -#line 49 +#line 52 i_0 = i_0 + int(1); -#line 49 +#line 52 result_0 = result_1; -#line 49 +#line 52 weightSum_0 = weightSum_1; -#line 49 +#line 52 } -#line 71 - return (float4)(result_0 / max(weightSum_0, 0.00009999999747379f)); +#line 74 + return (float4)(result_0 / weightSum_0); } diff --git a/Engine/shaders/slang/SSAOBlur.slang b/Engine/shaders/slang/SSAOBlur.slang index d9878ff3..048e11e8 100644 --- a/Engine/shaders/slang/SSAOBlur.slang +++ b/Engine/shaders/slang/SSAOBlur.slang @@ -46,7 +46,10 @@ float4 fragmentMain(VSOutput input) : SV_Target float weightSum = 0.0f; float variance = 0.01f; - for (int i = -2; i <= 2; ++i) + float w = 6.0f; + float s = w / 2.0f; + float s2 = 2.0f * s * s; + for (int i = -6; i <= 6; ++i) { float2 offset = float2(pushConstants.blurDirection.x * i, pushConstants.blurDirection.y * i) * texelSize; float2 sampleUV = input.uv + offset; @@ -56,11 +59,11 @@ float4 fragmentMain(VSOutput input) : SV_Target float3 sampleP = gPosition.SampleLevel(gSampler, sampleUV, 0).xyz; float sampleD = mul(pushConstants.view, float4(sampleP, 1.0f)).z; - float spatialWeight = exp(-(i * i) / 8.0f); + float spatialWeight = exp(-(i * i) / s2); float normalTerm = max(0.0f, dot(sampleN, centerN)); float depthDiff = sampleD - centerD; - float depthTerm = (1.0f / sqrt(2.0f * 3.141592f * variance)) * exp(-(depthDiff * depthDiff) / (2.0f * variance)); + float depthTerm = (1.0f / sqrt(2.0f * PI * variance)) * exp(-(depthDiff * depthDiff) / (2.0f * variance)); float weight = spatialWeight * normalTerm * depthTerm; @@ -68,5 +71,5 @@ float4 fragmentMain(VSOutput input) : SV_Target weightSum += weight; } - return result / max(weightSum, 0.0001f); + return result / weightSum; } diff --git a/Engine/shaders/spirv/SSAOBlur.frag.spv b/Engine/shaders/spirv/SSAOBlur.frag.spv index 99b03ecb0d6375f8166323a036c612d801e812db..31984812ac4056d7aad06804b9f424f3a9cc3fa4 100644 GIT binary patch literal 5676 zcmZvedyL#w6~}+=?(EjKKzWr%v2Lx8DzYdo1Z-M%ZFMQ>V_~7-a~XDL+o`)V&CDzm zwYnA18nIMTQVawM1mAB^@r{u9h=o6l5m6)&{vkpA$50E#)X(QP_ssr^z0J4hobNgJ zoO{pj-aFehcX@BtH7Com71_)D?>IS|o5?K5da?oJ(8iIC{ms^R|Ede$j+vd9bt&?g zld|5d8+|UADpzaryTKB$h&cIP(8a$6Nb{D^<*NUucW3kA8kOesWXrf$+oe3mjg{)Q z?X8jNseJzNIqO$zJEvRy(>I`!Yhm_U*|x6 z$~)=}wz+C0yX;|x@s9CwtE?<#^Rjc0!_&>}>*}>;t6Xa}M`K2Nj(*1t)yj>^9{$O> z@12eMj>=f8TBl1rbU@zzTt7M8SYK^~E3d83E;q{K)#>JJZhPGvD^FICk-LOGR#GwJ z=yFd5cU7g)zH{B#({Sy3*zUnI*t7Sxls((=$35-Jo`Y-O`JVjTzq;Q;tjBx16gafi zJ;#f{WvnIcr035u#4U+?q+i_;{@}cSaswbZ@1ERDf$K`#-U8>HGw!wm=be+=U*KG) zoZmlcc-Q3aDsbL4IlpPddC%nT1Mb^sUswyO8Rq6JrnhlHG^x{@t(qVj|sVUykm~{ppiCgV-~Z?)sd2 zHqyNE`d^1M*7cmr|4~c(9BkKaOdnWEEzgCVbC)5FH}_KBeb0n`q0hVl<3d-u7WeIX zofoy=fFAxgCck$0S0qkb{ydOnGnbx4rt{I{<^b0eL)&4^ceK?!_H3e7CjP?2YcFA+ z7bDFVbyg?8`(A@?9lz0O)nLyu=Zx8`?Wu3V(&oO+hXtQ*smNt zdNk%wWBa|G|1qRBofG~U^!T=W(9ORLg#UT;IpA%a3g^85>{$`3$?duDO)ys5Z?hbj zPusqER~*{*%e&wRzh~c}?OJyO*BgG%y2CU54`iPP!?kMvGq+r8DLG%)2>-;+~pK=ZJy-#NWdpJmK&+eOmJ@iZ)S&hxDLN2A|J+jG1M_>HzQ$Mfvp1IEZ-o6duO3&^{6d*wOb!b&~kYk_{@ zh<+}ld+y~@FaX{KjD3VUgUQyn4%oYeNXILz%h)r3oc&W@ON?jb1@JPQz1C+;?B(6) z?j`p69`qp)d)t66XI$*T$gEc_GtvjJDe+b6_B%Ta91bJ?-1P9#C0Xk8rS6dv2(9YJfbuAy@@N?p*789(c}H*`LYFJn7)@NU#&wA+)+oc-!{F@8^+4VcHOA28iZ#X) zSFBMSJ1_QILzj1N-i=J zo`PHq9Qsd0>Q`!?lx(H;qGT&Q?np%JnRhuan2~^JyR-dH13h^L_?f z&a)JGK8r42%yS#Ie7wP*LpQhlt?gz!U>+{%mfOxwO zpvxH-Z`YmZ^5*j#_|4;d97Naeu*UhwyTAp>w&oXrHKWGe=*GxLjeF4Li#6iyzZYJ= zaM&-`5qtU~dT~$pVGn_*cR#wEaZ&F9bot}edk|i~a1`tL_I?R$0rtSR_sfYx;t`#>-%eaH?mLMq*7$DX ziZ#9mXN_XqL)h|;Sl`3wa>W|oPh4^C4-!|b@k2Ok1UC=;5g_k~8b3mpE7tgN;)*qX zk~s6lJNZ*|`)_|-zxl)WGjzX$eR3bx3E$7r{T}wq{a7!2zd-l9*f;lOU46d2j{<9& z+Z@Km+xts&&)9h&-rmR1~aIL4U+Ph5i!IAKahNU9)Qm?rC&+$g literal 5704 zcmZvedyL#w6~}+=?rdvYpuAe3P+IGwiWH>_sgRbft!_*DSXe0dT!!7*cFOL|W@Z)& zDy=-U8k8!JR0C-Z1m8~-@Qp~~BSm725m6)&{viSV$Fvrs_4E17J+r@JZ}aUr=X=gQ z=iYPg{mphwUos=>nwDkR((G0Kcbu3_&tzt2Jy{>Jf5YI0WzE*evfc~cj+q^wbt&?g z6S5guH~MriUar>UcY+0AE^+cRKo|dJBh6bvm#hAt-kr^YYgC$(V=d!eYnSpIH&m)y zx3vZ*$MgBe=B!_>O-#0yOmt~uFR$f1qpR-?LOuvKrAw^oKm$Li%)?~dM~HTAKL zvXAy4#?Y|YsV%VYpacL<+b(M$O&+ z+@xz$d=GkUa(u8nJ~37)}%(4b*(@JCV(NQ6uZeIfXXgon17=6W5)s!XB>F zT9wA8JXb&V)`5Dn+HPTv$5OVZllRIksCn+Ykb{G(H@EGc>>iY3?eE?xo_VEgZ^xdR zdtZk;x;OVv@p;XC9oydYWDj)gqvt(1#pm-L>e%+7JA1NYuf;B9Ph*c%CR*FpR!2wC z<(>)dib|vX=DM?I;o9%8-Gk?_r`~NTd%ok3ciNS`0M~x=J^8(VZNK|jkMDLNaA>Q0 zkLQAQtR>#0_s`MKD~WfcU)>S@;Cz2_eIPjBp4_ei*Oj>41u{szrJAmuJk+fYZv{#75(l}zjo2@H@eto z@38Ui)p+fQKbb79V==w%LaLuij6GPC>_yn_-~GzZBhq~?%F&&&c(^^zE`4K$1^&G9IKHLw+8*G0|!>ddN*P_ti1{8e(ld`*xQlzw%GeR_J5BY zITG_HvE57LzX^T*qrY2WzMIiqL;HNXvs=*3zZk^)7tyDIw{a_sdkNUHA}%JE_rh<2 zvD%)^5@0@U`{rA5XxlH}f+PIieTTMd+X-A>_`T~6@ATi1i!>OnRr?>gUAw*Vo^NKQ-tkpH zzi>o9=g>X(atY`I?*hg?MxE8k*0%=OyE#b5tE|h|`9RM8sjni&yYdn^3}>(P854VX zH@bU?y}k#%AH?3)qsti=d%F}}{#bk40Iy#-VsD;{?{qWpTs8u0`ep}!{AI)}%w?NH z&AGFYmnS|r`!tyNB6mgNtZP2wu1uWg5Zso;btTRkSLJ$p%@KEX;t`#>?@e5>#`_Xi ztnvQD6>EGT&(ppWQR9Pf@{Zs>gf3UCF_gGsjcXEDtWk!$3(JKc z+qwmLD_8=|W39!=+km`1u=eeVLv+^jadg*nTZ;Jvx^eP#@_2uC1Nq4NN%UggPhrb> zmm<#{=<>xppT?GtZ}4Z(%`JaB_5Cj23FMc7k0ovoy5Adpu3!Sn<;~|k@XX_W>_yk_u*P}F&x7-mZOtzLYetRx(2bFg8uz2i7i+|~e;>Sl z;jmw>Blff(y|||@V)uin_W-)weh~E@M3+BSy@%lS3rDfuS=e6!n}I#>+xz9jA#%?5 z^%WrRh+cgaUEUGg*U;sx5!}}k=N^OmM&h~>XN_+HYZT{xEAfcV+;1nY826pT6>EGq zam5-B!&##k_dRTRN38Gr=yJsxk0h=*_tC@^Ydi*Ljo@aY{{YB4qQ(!=<%%_al(=Gz zA1BUy@tyn$y8X95uHXFO`zgBTV4vKFb;9>EbkDO>+0K%{5i0u zxy|u7h;Q!`=-#n&L413EfiCa7*zc3*^6o9Z55GkB+aPY{z4?9m6_Ahb&aV^ax4~Zi z2FM)(@%PdJ^ggfv=)XI~K83yytO9e`i}QaA`oL1)+c)Oc6#q23>#TvO_j`1C5!@fp z`^z9$n5n{&t*#^tVH)eQL6m=I|W;24;X=SlTZn?nPw$cFL){9@i1Soz^q& zJfwA$+Q%jPBxJ002fAyG^SKed4|qQMZUPbeVRUQxx4L`(2#|A5+~bcXUSGg Date: Thu, 9 Apr 2026 13:47:14 -0700 Subject: [PATCH 10/18] Minor Code Fix --- Game/include/ProceduralMeshes.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Game/include/ProceduralMeshes.hpp b/Game/include/ProceduralMeshes.hpp index 1965aecc..85a4bb0c 100644 --- a/Game/include/ProceduralMeshes.hpp +++ b/Game/include/ProceduralMeshes.hpp @@ -25,7 +25,7 @@ class ProceduralMeshes : public GameState MeshType currentMesh{ MeshType::PLANE }; //ImGui - Projection - float cNear{ 0.001f }, cFar{ 1000.f }; + float cNear{ 0.1f }, cFar{ 1000.f }; float cFov{ 22.5f }; //ImGui - Object std::filesystem::path objPath = ""; From 7e043edd8fdd9f7b2d9bb31610526affc8aeb574 Mon Sep 17 00:00:00 2001 From: rapt0r Date: Thu, 9 Apr 2026 13:48:11 -0700 Subject: [PATCH 11/18] Minor Code Fix --- Engine/source/Camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/Camera.cpp b/Engine/source/Camera.cpp index fd9a04a7..e81cf1ca 100644 --- a/Engine/source/Camera.cpp +++ b/Engine/source/Camera.cpp @@ -348,5 +348,5 @@ void Camera::SetViewSize(int width, int height) noexcept void Camera::SetZoom(float amount) noexcept { - zoom = glm::clamp(amount, nearClip, farClip); + zoom = glm::clamp(amount, 0.01f, 1000.f); } From 42089dd0b22db7d7da5e9b75956c8d7afb1819ed Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 22:03:31 -0700 Subject: [PATCH 12/18] Minor Code Fix --- Engine/shaders/slang/SSAOBlur.slang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/shaders/slang/SSAOBlur.slang b/Engine/shaders/slang/SSAOBlur.slang index 048e11e8..2d37a6e4 100644 --- a/Engine/shaders/slang/SSAOBlur.slang +++ b/Engine/shaders/slang/SSAOBlur.slang @@ -46,10 +46,10 @@ float4 fragmentMain(VSOutput input) : SV_Target float weightSum = 0.0f; float variance = 0.01f; - float w = 6.0f; + int w = 6.0f; float s = w / 2.0f; float s2 = 2.0f * s * s; - for (int i = -6; i <= 6; ++i) + for (int i = -w; i <= w; ++i) { float2 offset = float2(pushConstants.blurDirection.x * i, pushConstants.blurDirection.y * i) * texelSize; float2 sampleUV = input.uv + offset; From 9b375a24c16bd9f6a7e95ca4e0cffe74a7886b9f Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 22:16:25 -0700 Subject: [PATCH 13/18] Fixed Ambient Occlusion Resize Issue --- Engine/source/DXSSAOContext.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Engine/source/DXSSAOContext.cpp b/Engine/source/DXSSAOContext.cpp index e30ef75f..b0038081 100644 --- a/Engine/source/DXSSAOContext.cpp +++ b/Engine/source/DXSSAOContext.cpp @@ -63,6 +63,25 @@ void DXSSAOContext::Initialize() void DXSSAOContext::OnResize() { + m_ssaoTexture.Reset(); + m_ssaoRtvHeap.Reset(); + + m_blurIntermediateTexture.Reset(); + m_blurIntermediateRtvHeap.Reset(); + + m_blurTexture.Reset(); + m_blurRtvHeap.Reset(); + + m_renderManager->DeallocateSrvBlock(m_ssaoSrvHandle.second, 1); + m_renderManager->DeallocateSrvBlock(m_blurIntermediateSrvHandle.second, 1); + m_renderManager->DeallocateSrvBlock(m_blurSrvHandle.second, 1); + + CreateSSAOResources(); + CreateBlurResources(); + + D3D12_CPU_DESCRIPTOR_HANDLE destHandle = m_gBufferSrvHandle.first; + D3D12_CPU_DESCRIPTOR_HANDLE srcHandle = m_renderManager->GetGBufferContext()->GetSRVHeap()->GetCPUDescriptorHandleForHeapStart(); + m_renderManager->m_device->CopyDescriptorsSimple(4, destHandle, srcHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } void DXSSAOContext::Execute(ICommandListWrapper* commandListWrapper) From 880580d6efdf1c946d5848f12005541984eeecaf Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 22:45:26 -0700 Subject: [PATCH 14/18] Minor Code Fix --- Engine/shaders/slang/SSAOBlur.slang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/shaders/slang/SSAOBlur.slang b/Engine/shaders/slang/SSAOBlur.slang index 2d37a6e4..500fc1ef 100644 --- a/Engine/shaders/slang/SSAOBlur.slang +++ b/Engine/shaders/slang/SSAOBlur.slang @@ -46,8 +46,8 @@ float4 fragmentMain(VSOutput input) : SV_Target float weightSum = 0.0f; float variance = 0.01f; - int w = 6.0f; - float s = w / 2.0f; + int w = 6; + float s = (float)w / 2.0f; float s2 = 2.0f * s * s; for (int i = -w; i <= w; ++i) { From 43a6d9f98bae99c9f04f96195e6ea7ceee4cc0ba Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 23:33:34 -0700 Subject: [PATCH 15/18] Minor Code Fix --- Engine/include/DXRenderManager.hpp | 6 +++--- Engine/include/DXSSAOContext.hpp | 5 ++++- Engine/source/DXSSAOContext.cpp | 4 +--- Engine/source/RenderManager.cpp | 4 +++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Engine/include/DXRenderManager.hpp b/Engine/include/DXRenderManager.hpp index 6597a470..13312063 100644 --- a/Engine/include/DXRenderManager.hpp +++ b/Engine/include/DXRenderManager.hpp @@ -65,9 +65,9 @@ class DXRenderManager : public RenderManager bool BeginRender(glm::vec3 bgColor) override; void EndRender() override; - DXShadowMapContext* GetShadowMapContext() const { return m_shadowMapContext.get(); } - DXPostProcessContext* GetPostProcessContext() const { return m_postProcessContext.get(); } - DXSSAOContext* GetSSAOContext() const { return m_ssaoContext.get(); } + [[nodiscard]] DXShadowMapContext* GetShadowMapContext() const { return m_shadowMapContext.get(); } + [[nodiscard]] DXPostProcessContext* GetPostProcessContext() const { return m_postProcessContext.get(); } + [[nodiscard]] DXSSAOContext* GetSSAOContext() const { return m_ssaoContext.get(); } private: int m_width, m_height; bool m_isResize{ false }; diff --git a/Engine/include/DXSSAOContext.hpp b/Engine/include/DXSSAOContext.hpp index 4c5466d5..1a0810c5 100644 --- a/Engine/include/DXSSAOContext.hpp +++ b/Engine/include/DXSSAOContext.hpp @@ -20,7 +20,10 @@ class DXSSAOContext : public IRenderContext void Execute(ICommandListWrapper* commandListWrapper) override; void CleanUp() override; - UINT GetBlurredAOSrvIndex() const { return m_blurSrvHandle.second; } + void SetEnabled(bool enabled) { m_enabled = enabled; } + + [[nodiscard]] UINT GetBlurredAOSrvIndex() const { return m_blurSrvHandle.second; } + [[nodiscard]] bool IsEnabled() const { return m_enabled; } void DrawImGui(); private: diff --git a/Engine/source/DXSSAOContext.cpp b/Engine/source/DXSSAOContext.cpp index b0038081..caee38de 100644 --- a/Engine/source/DXSSAOContext.cpp +++ b/Engine/source/DXSSAOContext.cpp @@ -317,10 +317,8 @@ void DXSSAOContext::CreateBlurResources() void DXSSAOContext::DrawImGui() { - if (ImGui::CollapsingHeader("Ambient Occlusion (Alchemy AO)")) + if (ImGui::CollapsingHeader("Ambient Occlusion Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Enable SSAO", &m_enabled); - if (m_enabled) { ImGui::SliderFloat("Radius", &m_radius, 0.01f, 2.0f, "%.3f"); diff --git a/Engine/source/RenderManager.cpp b/Engine/source/RenderManager.cpp index 9640fe96..8d0b283f 100644 --- a/Engine/source/RenderManager.cpp +++ b/Engine/source/RenderManager.cpp @@ -1262,7 +1262,9 @@ void RenderManager::RenderingControllerForImGui() if (shadowEnabled) dxRenderManager->GetShadowMapContext()->DrawImGui(); // SSAO Context - dxRenderManager->GetSSAOContext()->DrawImGui(); + bool ssaoEnabled = dxRenderManager->GetSSAOContext()->IsEnabled(); + if (ImGui::Checkbox("Ambient Occlusion (Alchemy AO)", &ssaoEnabled)) dxRenderManager->GetSSAOContext()->SetEnabled(ssaoEnabled); + if (dxRenderManager->GetSSAOContext()->IsEnabled()) dxRenderManager->GetSSAOContext()->DrawImGui(); } ImGui::End(); From 5b4c09cd67ab9233edc107a946768622566448df Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 23:39:28 -0700 Subject: [PATCH 16/18] Toggle SSAO --- Engine/include/DXGlobalLightingContext.hpp | 1 + Engine/shaders/slang/GlobalLightingPass.slang | 4 +++- Engine/source/DXGlobalLightingContext.cpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Engine/include/DXGlobalLightingContext.hpp b/Engine/include/DXGlobalLightingContext.hpp index 10afe6b4..6aa59189 100644 --- a/Engine/include/DXGlobalLightingContext.hpp +++ b/Engine/include/DXGlobalLightingContext.hpp @@ -35,5 +35,6 @@ class DXGlobalLightingContext : public IRenderContext int activeDirectionalLight; int useShadow; float orthoSize; + int useSSAO; } pushConstants; }; diff --git a/Engine/shaders/slang/GlobalLightingPass.slang b/Engine/shaders/slang/GlobalLightingPass.slang index b917c994..b930c840 100644 --- a/Engine/shaders/slang/GlobalLightingPass.slang +++ b/Engine/shaders/slang/GlobalLightingPass.slang @@ -55,6 +55,7 @@ struct PushConstants int activeDirectionalLights; int useShadow; float orthoSize; + int useSSAO; } #if defined(__hlsl__) ConstantBuffer pushConstants : register(b1, space0); @@ -314,7 +315,8 @@ float4 fragmentMain(VSOutput input) : SV_Target #endif float3 specular = prefilteredColor * (F * brdf.x + brdf.y); - float ao = SSAO.Sample(gSampler, input.uv).r; + float ao = 1.0; + if (pushConstants.useSSAO > 0) ao = SSAO.Sample(gSampler, input.uv).r; float3 ambient = (Kd * diffuse + specular) * ao; resultColor = ambient + resultColor; diff --git a/Engine/source/DXGlobalLightingContext.cpp b/Engine/source/DXGlobalLightingContext.cpp index 855599aa..ac3b046d 100644 --- a/Engine/source/DXGlobalLightingContext.cpp +++ b/Engine/source/DXGlobalLightingContext.cpp @@ -97,7 +97,8 @@ void DXGlobalLightingContext::Execute(ICommandListWrapper* commandListWrapper) .meshletVisualization = m_renderManager->m_meshletVisualization ? 1 : 0, .activeDirectionalLight = static_cast(m_renderManager->directionalLightUniforms.size()), .useShadow = m_renderManager->m_shadowMapContext->IsEnabled() ? 1 : 0, - .orthoSize = m_renderManager->m_shadowMapContext->GetOrthoSize() + .orthoSize = m_renderManager->m_shadowMapContext->GetOrthoSize(), + .useSSAO = m_renderManager->GetSSAOContext()->IsEnabled() ? 1 : 0 }; commandList->SetGraphicsRoot32BitConstants(1, sizeof(PushConstants) / 4, &pushConstants, 0); From 4e592d0f0976dd17d8a13832f8357a5c43d3f71a Mon Sep 17 00:00:00 2001 From: rapt0r Date: Sun, 12 Apr 2026 23:40:22 -0700 Subject: [PATCH 17/18] Toggle SSAO Shader Compile --- .../shaders/hlsl/GlobalLightingPass.frag.hlsl | 123 +++++++++++------- .../shaders/spirv/GlobalLightingPass.frag.spv | Bin 11248 -> 11500 bytes 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl b/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl index 03be1d22..adc05cd4 100644 --- a/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl +++ b/Engine/shaders/hlsl/GlobalLightingPass.frag.hlsl @@ -9,7 +9,7 @@ #endif -#line 65 "slang/GlobalLightingPass.slang" +#line 66 "slang/GlobalLightingPass.slang" Texture2D gAlbedo_0 : register(t0, space1); @@ -27,6 +27,7 @@ struct PushConstants_0 int activeDirectionalLights_0; int useShadow_0; float orthoSize_0; + int useSSAO_0; }; cbuffer pushConstants_0 : register(b1) @@ -38,19 +39,19 @@ cbuffer pushConstants_0 : register(b1) Texture2D gNormal_0 : register(t1, space1); -#line 67 +#line 68 Texture2D gPosition_0 : register(t2, space1); -#line 68 +#line 69 Texture2D gMaterial_0 : register(t3, space1); -#line 81 +#line 82 Texture2D shadowMap_0 : register(t3, space2); -#line 82 +#line 83 SamplerState iblSmp_0 : register(s1, space2); @@ -76,23 +77,23 @@ cbuffer directionalLightList_0 : register(b0) fDirectionalLightList_0 directionalLightList_0; } -#line 73 +#line 74 TextureCube irradianceMap_0 : register(t0, space2); -#line 74 +#line 75 TextureCube prefilterMap_0 : register(t1, space2); -#line 75 +#line 76 Texture2D brdfLUT_0 : register(t2, space2); -#line 69 +#line 70 Texture2D SSAO_0 : register(t4, space1); -#line 169 +#line 170 struct MainVectors_0 { float3 worldPosition_0; @@ -104,11 +105,11 @@ struct MainVectors_0 }; -#line 169 +#line 170 MainVectors_0 MainVectors_x24init_0(float3 worldPosition_1, float3 albedo_1, float4 material_1, float3 V_1, float3 N_1, float3 F0_1) { -#line 169 +#line 170 MainVectors_0 _S1; _S1.worldPosition_0 = worldPosition_1; @@ -118,7 +119,7 @@ MainVectors_0 MainVectors_x24init_0(float3 worldPosition_1, float3 albedo_1, flo _S1.N_0 = N_1; _S1.F0_0 = F0_1; -#line 169 +#line 170 return _S1; } @@ -204,19 +205,19 @@ float Hamburger4MSM_0(float4 b_0, float z_f_0) } -#line 159 "slang/GlobalLightingPass.slang" +#line 160 "slang/GlobalLightingPass.slang" float3 F_0(float3 F0_2, float3 V_2, float3 H_0) { return F0_2 + ((float3)1.0f - F0_2) * pow(1.0f - max(dot(V_2, H_0), 0.0f), 5.0f); } -#line 129 +#line 130 float D_0(float alpha_0, float3 N_2, float3 H_1) { float numerator_0 = pow(alpha_0, 2.0f); -#line 137 +#line 138 return numerator_0 / max(3.14159274101257324f * pow(pow(max(dot(N_2, H_1), 0.0f), 2.0f) * (numerator_0 - 1.0f) + 1.0f, 2.0f), 9.99999997475242708e-07f); } @@ -239,13 +240,13 @@ float G_1(float alpha_2, float3 N_4, float3 V_3, float3 L_0) } -#line 180 +#line 181 float3 PBR_0(MainVectors_0 mainVectors_0, float3 lightPosition_0, float3 lightColor_1, int lightIndex_0) { float roughness_0 = mainVectors_0.material_0.y; -#line 188 +#line 189 float3 L_1 = normalize(- lightPosition_0); @@ -255,17 +256,17 @@ float3 PBR_0(MainVectors_0 mainVectors_0, float3 lightPosition_0, float3 lightCo float3 Ks_0 = F_0(mainVectors_0.F0_0, mainVectors_0.V_0, H_2); -#line 201 +#line 202 float alpha_3 = roughness_0 * roughness_0; float _S6 = max(dot(L_1, mainVectors_0.N_0), 0.0f); -#line 210 +#line 211 return ((1.0f - mainVectors_0.material_0.x) * ((float3)1.0f - Ks_0) * (mainVectors_0.albedo_0 / 3.14159274101257324f) + D_0(alpha_3, mainVectors_0.N_0, H_2) * G_1(alpha_3, mainVectors_0.N_0, mainVectors_0.V_0, L_1) * Ks_0 / max(4.0f * max(dot(mainVectors_0.V_0, mainVectors_0.N_0), 0.0f) * _S6, 0.10000000149011612f)) * lightColor_1 * _S6; } -#line 164 +#line 165 float3 Froughness_0(float3 F0_3, float3 V_4, float3 H_3, float roughness_1) { return F0_3 + (max((float3)(1.0f - roughness_1), F0_3) - F0_3) * pow(clamp(1.0f - max(dot(H_3, V_4), 0.0f), 0.0f, 1.0f), 5.0f); @@ -280,11 +281,11 @@ struct VSOutput_0 }; -#line 214 +#line 215 float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET { -#line 214 +#line 215 VSOutput_0 _S7 = input_0; float3 _S8 = (float3)0.0f; @@ -293,20 +294,20 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET if((albedoSample_0.w) < 0.00999999977648258f) { -#line 219 +#line 220 discard; -#line 219 +#line 220 } float3 albedo_2 = albedoSample_0.xyz; if((pushConstants_0.meshletVisualization_0) > int(0)) { -#line 221 +#line 222 return float4(albedo_2, 1.0f); } -#line 222 +#line 223 float3 normal_0 = gNormal_0.Sample(gSampler_0, _S7.uv_0).xyz; float3 worldPosition_2 = gPosition_0.Sample(gSampler_0, _S7.uv_0).xyz; float4 material_2 = gMaterial_0.Sample(gSampler_0, _S7.uv_0); @@ -321,10 +322,10 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET float3 N_5 = normalize(normal_0); MainVectors_0 _S9 = MainVectors_x24init_0(worldPosition_2, albedo_2, material_2, V_5, N_5, F0_4); -#line 234 +#line 235 float shadow_0; -#line 247 +#line 248 if((pushConstants_0.useShadow_0) > int(0)) { @@ -339,63 +340,93 @@ float4 fragmentMain(VSOutput_0 input_0) : SV_TARGET shadowUV_0[int(1)] = - projectionCoords_0.y * 0.5f + 0.5f; -#line 265 +#line 266 float z_f_1 = projectionCoords_0.z; -#line 265 +#line 266 shadow_0 = Hamburger4MSM_0(shadowMap_0.Sample(iblSmp_0, shadowUV_0), z_f_1) * (step(0.0f, shadowUV_0.x) * step(shadowUV_0.x, 1.0f) * step(0.0f, shadowUV_0.y) * step(shadowUV_0.y, 1.0f) * step(0.0f, z_f_1) * step(z_f_1, 1.0f)); -#line 247 +#line 248 } else { -#line 247 +#line 248 shadow_0 = 0.0f; -#line 247 +#line 248 } -#line 247 +#line 248 int l_0 = int(0); -#line 247 +#line 248 float3 resultColor_0 = _S8; -#line 287 +#line 288 for(;;) { -#line 287 +#line 288 if(l_0 < (pushConstants_0.activeDirectionalLights_0)) { } else { -#line 287 +#line 288 break; } float3 resultColor_1 = resultColor_0 + PBR_0(_S9, directionalLightList_0.lights_0[l_0].lightDirection_0, directionalLightList_0.lights_0[l_0].lightColor_0 * directionalLightList_0.lights_0[l_0].intensity_0, l_0) * (1.0f - shadow_0); -#line 287 +#line 288 l_0 = l_0 + int(1); -#line 287 +#line 288 resultColor_0 = resultColor_1; -#line 287 +#line 288 } -#line 296 +#line 297 float3 F_1 = Froughness_0(F0_4, V_5, N_5, roughness_2); -#line 310 + + float3 Kd_0 = (1.0f - metallic_0) * ((float3)1.0f - F_1); + +#line 306 + float3 diffuse_0 = irradianceMap_0.Sample(iblSmp_0, N_5).xyz * albedo_2; + +#line 311 float2 brdf_0 = brdfLUT_0.Sample(iblSmp_0, float2(max(dot(N_5, V_5), 0.0f), roughness_2)).xy; -#line 332 - return float4(((1.0f - metallic_0) * ((float3)1.0f - F_1) * (irradianceMap_0.Sample(iblSmp_0, N_5).xyz * albedo_2) + prefilterMap_0.SampleLevel(iblSmp_0, reflect(- V_5, N_5), roughness_2 * 4.0f).xyz * (F_1 * brdf_0.x + brdf_0.y)) * SSAO_0.Sample(gSampler_0, _S7.uv_0).x + resultColor_0, 1.0f); +#line 316 + float3 specular_0 = prefilterMap_0.SampleLevel(iblSmp_0, reflect(- V_5, N_5), roughness_2 * 4.0f).xyz * (F_1 * brdf_0.x + brdf_0.y); + +#line 316 + float ao_0; + + + if((pushConstants_0.useSSAO_0) > int(0)) + { + +#line 319 + ao_0 = SSAO_0.Sample(gSampler_0, _S7.uv_0).x; + +#line 319 + } + else + { + +#line 319 + ao_0 = 1.0f; + +#line 319 + } + +#line 334 + return float4((Kd_0 * diffuse_0 + specular_0) * ao_0 + resultColor_0, 1.0f); } diff --git a/Engine/shaders/spirv/GlobalLightingPass.frag.spv b/Engine/shaders/spirv/GlobalLightingPass.frag.spv index 12733a8305af87e83c7937d7e9b0112e8e436049..0d226f79b229e74aae073ffb83a46173cf755cfa 100644 GIT binary patch literal 11500 zcmZvi3zVE?dB;DpmxK@`C`Lhz!PHy96iWaF5|ZY!3E7avC8>%UCfV8S!0gU4Gn)`V z6F@MwirhpYg5iF@qXGd*Tku#5G=iwDt>@U%_MF<%dO59#x8LuZ_nG~6$wwaE=lMVP z_x8<9(lKT3)U0E_EX&@Lt?6LkIXIh=i5!r1XH~|Y-u~Wsjpo3-`Ntfk{&iW)P@99Y zsaYrE6ll0q8DYroLh&bzGqDq&3U%<`0gU=|;UU%-Dh<@O>`U&-rnmKL*TLemFRUXw z5S=x45r3TTB6pV6%Z;&Wb4jgQtLOf IU%SyGD|2W^3*IyYK9c#`T+l&eRo!QZh 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 CPvlns literal 11248 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 G2K^56-oVrV From c7e6fc5699e4438c05f8951718d267985400146e Mon Sep 17 00:00:00 2001 From: rapt0r <80149097+CubeBerry@users.noreply.github.com> Date: Mon, 13 Apr 2026 00:15:35 -0700 Subject: [PATCH 18/18] Add SSAO (Alchemy AO) support status to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 37387084..44392cd1 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,7 @@ dxc WorkGraphs.hlsl -T lib_6_8 -E broadcastNode -Fo WorkGraphs.cso | PBR (Physically Based Rendering) | ➖ | ✅ | ✅ | ✅ | | IBL (Image Based Lighting) | ➖ | ✅ | ✅ | ✅ | | Moment Shadow Mapping | ➖ | ❌ | ❌ | ✅ | +| SSAO (Alchemy AO) | ➖ | ❌ | ❌ | ✅ | | Skybox | ➖ | ✅ | ✅ | ✅ | | Normal Vector Visualization | ➖ | ✅ | ✅ | ✅ | | [Assimp Model Loading](https://github.com/assimp/assimp) | ✅ | ➖ | ➖ | ➖ |