SSAO sort of working

This commit is contained in:
Brandon Mak 2022-10-31 20:49:28 +08:00
parent 94a57219da
commit 2bd3b45ba0
17 changed files with 174 additions and 37 deletions

View File

@ -21,7 +21,8 @@ layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData;
layout(set = 4, binding = 4, rgba8) uniform image2D targetImage;
layout(set = 4, binding = 4, rgba32f) uniform image2D ssaoImage;
layout(set = 4, binding = 5, rgba8) uniform image2D targetImage;
layout(set = 1, binding = 0) uniform LightCounts
{
@ -78,6 +79,7 @@ void main()
}
// store result into result image
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(imageLoad(ssaoImage, globalThread).rgb, 1.0f));
}

View File

@ -1,7 +1,13 @@
#version 450
uint const NUM_SAMPLES = 64;
uint const NUM_ROTATIONS = 16;
const uint NUM_SAMPLES = 64;
const uint NUM_ROTATIONS = 16;
const int ROTATION_KERNEL_W = 4;
const int ROTATION_KERNEL_H = 4;
// can perhaps pass in as push constant.
const float RADIUS = 0.5f;
const float BIAS = 0.025f;
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
@ -12,13 +18,75 @@ layout(set = 4, binding = 2, rgba32f) uniform image2D outputImage;
// SSAO data
layout(std430, set = 5, binding = 0) buffer SSAOData
{
vec3 samples[NUM_SAMPLES];
vec3 rotations[NUM_ROTATIONS];
vec4 samples[NUM_SAMPLES];
vec4 rotations[NUM_ROTATIONS];
} ssaoData;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData;
shared vec4 sharedRotations[NUM_ROTATIONS];
void main()
{
ivec2 size = imageSize (outputImage);
// load rotations into shared memory
uint localThreadIndex = gl_LocalInvocationIndex;
if (localThreadIndex < NUM_ROTATIONS)
sharedRotations[localThreadIndex] = ssaoData.rotations[localThreadIndex];
barrier();
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
// load all the necessary variables
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
// Get random vector
uint randomVecXIndex = globalThread.x % ROTATION_KERNEL_W;
uint randomVecYIndex = globalThread.y % ROTATION_KERNEL_H;
vec3 randomVec = (sharedRotations[randomVecYIndex * ROTATION_KERNEL_W + randomVecXIndex].rgb) * 2.0f - 1.0f;
// Gram schmidt
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
vec3 bitangent = cross (tangent, viewSpaceNormal);
mat3 TBN = mat3 (tangent, bitangent, viewSpaceNormal);
float occlusion = 0.0f;
for (int i = 0; i < NUM_SAMPLES; ++i)
{
// We want to get a position at an offset from the view space position. Offset scaled by radius.
vec3 samplePos = TBN * ssaoData.samples[i].rgb;
samplePos = viewSpacePos + samplePos * RADIUS;
// Now we take that offset position and bring it to clip space
vec4 offsetPos = vec4 (samplePos, 1.0f);
offsetPos = cameraData.projMat * offsetPos;
// then we do perspective division
offsetPos.xyz /= offsetPos.w;
// and bring it from [-1, 1] to screen coordinates
offsetPos.xyz = ((offsetPos.xyz * 0.5f) + 0.5f);
offsetPos.xy *= vec2(size.xy);
float sampleDepth = imageLoad (positions, ivec2 (offsetPos.xy)).z;
float rangeCheck = smoothstep (0.0f, 1.0f, RADIUS / abs (viewSpacePos.z - sampleDepth));
occlusion += (sampleDepth >= samplePos.z + BIAS ? 1.0f : 0.0f) * rangeCheck;
}
occlusion = (occlusion / float(NUM_SAMPLES));
// store result into result image
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), vec4(occlusion.rrr, 0.0f));
}

Binary file not shown.

View File

@ -34,6 +34,7 @@ layout(set = 2, binding = 0) uniform CameraData
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData;
void main()
@ -51,8 +52,10 @@ void main()
// uvs for texturing in fragment shader
Out.uv = aUV;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
// normals are also in view space
Out.normal.rgb = mat3(transpose(inverse(modelViewMat))) * aNormal.rgb;
Out.normal.rgb = transposeInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb);
// clip space for rendering

Binary file not shown.

View File

@ -64,6 +64,11 @@ namespace SHADE
return bufferUsageFlags;
}
uint32_t SHVkBuffer::GetSizeStored(void) const noexcept
{
return sizeStored;
}
/***************************************************************************/
/*!

View File

@ -102,8 +102,9 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Buffer GetVkBuffer (void) const noexcept;
vk::Buffer GetVkBuffer (void) const noexcept;
vk::BufferUsageFlags GetUsageBits(void) const noexcept;
uint32_t GetSizeStored (void) const noexcept;
template <typename T>
T GetDataFromMappedPointer(uint32_t index) const noexcept

View File

@ -79,7 +79,7 @@ namespace SHADE
SHVkDescriptorSetLayout::Binding cameraDataBinding
{
.Type = vk::DescriptorType::eUniformBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex,
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
.DescriptorCount = 1,
};

View File

@ -129,6 +129,7 @@ namespace SHADE
*/
/***************************************************************************/
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
};
struct VertexBufferBindings

View File

@ -37,6 +37,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Assets/Asset Types/SHTextureAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Assets/SHAssetManager.h"
namespace SHADE
@ -113,6 +114,7 @@ namespace SHADE
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl");
shaderModuleLibrary.ImportAllShaderSource(device);
shaderModuleLibrary.ReflectAllShaderModules();
@ -154,57 +156,95 @@ namespace SHADE
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
}
/*-----------------------------------------------------------------------*/
/* SCENE RENDER GRAPH RESOURCES */
/*-----------------------------------------------------------------------*/
// Initialize world render graph
worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
/*-----------------------------------------------------------------------*/
/* MAIN NODE */
/*-----------------------------------------------------------------------*/
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer",
{
"Position",
"Entity ID",
"Light Layer Indices",
"Normals",
//"Tangents",
"Albedo",
"Depth Buffer",
"Scene"
"Scene",
"SSAO"
},
{}); // no predecessors
/*-----------------------------------------------------------------------*/
/* G-BUFFER SUBPASS INIT */
/*-----------------------------------------------------------------------*/
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices");
gBufferSubpass->AddColorOutput("Normals");
//gBufferSubpass->AddColorOutput("Tangents");
gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
//// kirsch
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
//gBufferNode->AddNodeCompute(kirschShader, { "Position", "Scene" });
/*-----------------------------------------------------------------------*/
/* SSAO PASS AND DATA INIT */
/*-----------------------------------------------------------------------*/
ssaoStorage = resourceManager.Create<SHSSAO>();
//// copy
//auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
//gBufferNode->AddNodeCompute(pureCopyShader, { "Position", "Scene" });
ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
ssaoTransferCmdBuffer->BeginRecording();
// deferred composite
ssaoStorage->Init(device, ssaoTransferCmdBuffer);
ssaoTransferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ ssaoTransferCmdBuffer });
graphicsQueue->WaitIdle();
auto ssaoShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAO_CS");
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
auto ssaoDataBuffer = ssaoStorage->GetBuffer();
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BINDING, {&ssaoDataBuffer, 1}, 0, ssaoStorage->GetBuffer()->GetSizeStored());
/*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/
auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS");
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" });
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO", "Scene" });
/*-----------------------------------------------------------------------*/
/* DUMMY SUBPASS TO TRANSITION SCENE FOR PRESENT USAGE */
/*-----------------------------------------------------------------------*/
// Dummy to transition scene to be used for shader read
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene");
/*-----------------------------------------------------------------------*/
/* GENERATE RENDER GRAPH */
/*-----------------------------------------------------------------------*/
// Generate world render graph
worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/
// Add world renderer to default viewport
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
@ -254,17 +294,6 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool);
ssaoStorage = resourceManager.Create<SHSSAO>();
ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
ssaoTransferCmdBuffer->BeginRecording();
ssaoStorage->Init(device, ssaoTransferCmdBuffer);
ssaoTransferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ssaoTransferCmdBuffer});
graphicsQueue->WaitIdle();
}
#ifdef SHEDITOR

View File

@ -88,7 +88,7 @@ namespace SHADE
}
}
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix viewMatrix, SHMatrix projMatrix) noexcept
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
{
SetViewProjectionMatrix(viewMatrix, projMatrix);
@ -98,17 +98,19 @@ namespace SHADE
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{
}
void SHRenderer::SetViewProjectionMatrix(SHMatrix viewMatrix, SHMatrix projMatrix) noexcept
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
{
//cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix();
cpuCameraData.viewProjectionMatrix = SHMatrix::Transpose(projMatrix * viewMatrix);
cpuCameraData.viewMatrix = SHMatrix::Transpose(viewMatrix);
cpuCameraData.projectionMatrix = SHMatrix::Transpose(projMatrix);
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept

View File

@ -47,6 +47,7 @@ namespace SHADE
SHVec4 cameraPosition;
SHMatrix viewProjectionMatrix;
SHMatrix viewMatrix;
SHMatrix projectionMatrix;
};
/*---------------------------------------------------------------------------------*/
@ -80,9 +81,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix viewMatrix, SHMatrix projMatrix) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix viewMatrix, SHMatrix projMatrix) noexcept;
void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
/*-----------------------------------------------------------------------------*/
/* Setters and Getters */

View File

@ -39,7 +39,7 @@ namespace SHADE
auto& rotationVectors = ssaoData->rotatationVectors;
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
{
samples[i] = SHVec4
rotationVectors[i] = SHVec4
{
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
@ -57,4 +57,9 @@ namespace SHADE
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
}
Handle<SHVkBuffer> SHSSAO::GetBuffer(void) const noexcept
{
return ssaoDataBuffer;
}
}

View File

@ -12,6 +12,9 @@ namespace SHADE
class SHSSAO
{
public:
static constexpr uint32_t DESC_SET_BINDING = 0;
private:
static constexpr uint32_t NUM_SAMPLES = 64;
static constexpr uint32_t NUM_ROTATION_VECTORS = 16;
@ -33,5 +36,6 @@ namespace SHADE
public:
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
Handle<SHVkBuffer> GetBuffer (void) const noexcept;
};
}

View File

@ -82,6 +82,11 @@ namespace SHADE
// bind descriptor sets
cmdBuffer->BindDescriptorSet(graphResourceDescSets[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
if (computeResource)
{
cmdBuffer->BindDescriptorSet(computeResource->descSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, computeResource->dynamicOffsets[frameIndex]);
}
// dispatch compute
cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
@ -167,6 +172,7 @@ namespace SHADE
void SHRenderGraphNodeCompute::ModifyWriteDescBufferComputeResource(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
{
computeResource->descSet->ModifyWriteDescBuffer(set, binding, buffers, offset, range);
computeResource->descSet->UpdateDescriptorSetBuffer(set, binding);
}
}

View File

@ -142,6 +142,16 @@ namespace SHADE
case SpvOp::SpvOpTypeRuntimeArray:
recurseForInfo(&member, interfaceHdl, member.offset, biggestAlignment, parentVarName + std::string(member.name) + ".");
break;
case SpvOp::SpvOpTypeArray:
interfaceHdl->AddVariable(parentVarName + std::string (member.name),
SHShaderBlockInterface::Variable
(
parentOffset + member.offset,
SHShaderBlockInterface::Variable::Type::OTHER
)
);
biggestAlignment = std::max(biggestAlignment, member.size);
break;
}
}
};