SSAO WIP
This commit is contained in:
parent
441207260b
commit
53b9c8f746
|
@ -19,10 +19,11 @@ layout(set = 4, binding = 2, rgba32f) uniform image2D outputImage;
|
||||||
layout(std430, set = 5, binding = 0) buffer SSAOData
|
layout(std430, set = 5, binding = 0) buffer SSAOData
|
||||||
{
|
{
|
||||||
vec4 samples[NUM_SAMPLES];
|
vec4 samples[NUM_SAMPLES];
|
||||||
vec4 rotations[NUM_ROTATIONS];
|
|
||||||
|
|
||||||
} ssaoData;
|
} ssaoData;
|
||||||
|
|
||||||
|
layout (set = 5, binding = 1) uniform sampler2D noiseTexture;
|
||||||
|
|
||||||
layout(set = 2, binding = 0) uniform CameraData
|
layout(set = 2, binding = 0) uniform CameraData
|
||||||
{
|
{
|
||||||
vec4 position;
|
vec4 position;
|
||||||
|
@ -32,33 +33,28 @@ layout(set = 2, binding = 0) uniform CameraData
|
||||||
|
|
||||||
} cameraData;
|
} cameraData;
|
||||||
|
|
||||||
shared vec4 sharedRotations[NUM_ROTATIONS];
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ivec2 size = imageSize (outputImage);
|
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);
|
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
|
||||||
|
|
||||||
// load all the necessary variables
|
// load all the necessary variables
|
||||||
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
|
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
|
||||||
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
|
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
|
||||||
|
|
||||||
// Get random vector
|
ivec2 noiseDim = textureSize(noiseTexture, 0);
|
||||||
uint randomVecXIndex = globalThread.x % ROTATION_KERNEL_W;
|
vec2 threadUV = globalThread / size;
|
||||||
uint randomVecYIndex = globalThread.y % ROTATION_KERNEL_H;
|
vec2 noiseUV = vec2 (float(size.x)/float(noiseDim.x), float(size.y) / float(noiseDim.y));
|
||||||
vec3 randomVec = (sharedRotations[randomVecYIndex * ROTATION_KERNEL_W + randomVecXIndex].rgb) * 2.0f - 1.0f;
|
noiseUV *= threadUV;
|
||||||
|
vec3 randomVec = texture(noiseTexture, noiseUV).rgb * 2.0f - 1.0f;
|
||||||
|
|
||||||
// Gram schmidt
|
// Gram schmidt
|
||||||
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
|
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
|
||||||
vec3 bitangent = cross (tangent, viewSpaceNormal);
|
vec3 bitangent = cross (tangent, viewSpaceNormal);
|
||||||
|
|
||||||
|
// matrix for tangent to view
|
||||||
mat3 TBN = mat3 (tangent, bitangent, viewSpaceNormal);
|
mat3 TBN = mat3 (tangent, bitangent, viewSpaceNormal);
|
||||||
|
|
||||||
float occlusion = 0.0f;
|
float occlusion = 0.0f;
|
||||||
|
@ -85,7 +81,7 @@ void main()
|
||||||
occlusion += (sampleDepth >= samplePos.z + BIAS ? 1.0f : 0.0f) * rangeCheck;
|
occlusion += (sampleDepth >= samplePos.z + BIAS ? 1.0f : 0.0f) * rangeCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
occlusion = (occlusion / float(NUM_SAMPLES));
|
occlusion = 1.0f - (occlusion / float(NUM_SAMPLES));
|
||||||
|
|
||||||
// store result into result image
|
// store result into result image
|
||||||
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), vec4(occlusion.rrr, 0.0f));
|
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), vec4(occlusion.rrr, 0.0f));
|
||||||
|
|
Binary file not shown.
|
@ -215,10 +215,15 @@ namespace SHADE
|
||||||
|
|
||||||
graphicsQueue->WaitIdle();
|
graphicsQueue->WaitIdle();
|
||||||
|
|
||||||
|
ssaoStorage->PrepareRotationVectorsVkData(device);
|
||||||
|
|
||||||
auto ssaoShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAO_CS");
|
auto ssaoShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAO_CS");
|
||||||
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
|
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
|
||||||
auto ssaoDataBuffer = ssaoStorage->GetBuffer();
|
auto ssaoDataBuffer = ssaoStorage->GetBuffer();
|
||||||
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BINDING, {&ssaoDataBuffer, 1}, 0, ssaoStorage->GetBuffer()->GetSizeStored());
|
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored());
|
||||||
|
|
||||||
|
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
|
||||||
|
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
#include "SHSSAO.h"
|
#include "SHSSAO.h"
|
||||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
|
#include "Graphics/Images/SHVkImage.h"
|
||||||
|
#include "Graphics/Images/SHVkSampler.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
void SHSSAO::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
void SHSSAO::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||||
{
|
{
|
||||||
// create memory on CPU side
|
|
||||||
ssaoData = std::make_unique<SamplesAndKernel>();
|
|
||||||
|
|
||||||
// Initialize a distribution to get values from 0 to 1
|
// Initialize a distribution to get values from 0 to 1
|
||||||
std::uniform_real_distribution<float> distrib{0.0f, 1.0f};
|
std::uniform_real_distribution<float> distrib{0.0f, 1.0f};
|
||||||
|
|
||||||
|
@ -18,7 +17,6 @@ namespace SHADE
|
||||||
std::default_random_engine generator;
|
std::default_random_engine generator;
|
||||||
|
|
||||||
// generate samples
|
// generate samples
|
||||||
auto& samples = ssaoData->samples;
|
|
||||||
for (uint32_t i = 0; i < NUM_SAMPLES; ++i)
|
for (uint32_t i = 0; i < NUM_SAMPLES; ++i)
|
||||||
{
|
{
|
||||||
samples[i] = SHVec4
|
samples[i] = SHVec4
|
||||||
|
@ -36,7 +34,6 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate rotation vector
|
// generate rotation vector
|
||||||
auto& rotationVectors = ssaoData->rotatationVectors;
|
|
||||||
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
|
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
|
||||||
{
|
{
|
||||||
rotationVectors[i] = SHVec4
|
rotationVectors[i] = SHVec4
|
||||||
|
@ -48,15 +45,74 @@ namespace SHADE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHImageCreateParams imageDetails =
|
||||||
|
{
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.width = NUM_ROTATION_VECTORS_W,
|
||||||
|
.height = NUM_ROTATION_VECTORS_H,
|
||||||
|
.depth = 1,
|
||||||
|
.levels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.imageFormat = vk::Format::eR32G32B32A32Sfloat,
|
||||||
|
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
|
||||||
|
.createFlags = {}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t mipOffset = 0;
|
||||||
|
rotationVectorsImage = logicalDevice->CreateImage(imageDetails, reinterpret_cast<unsigned char*>( rotationVectors.data()), static_cast<uint32_t>(sizeof(rotationVectors)), {&mipOffset, 1}, VMA_MEMORY_USAGE_AUTO, {});
|
||||||
|
|
||||||
|
vk::ImageMemoryBarrier transferBarrier{};
|
||||||
|
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, transferBarrier);
|
||||||
|
|
||||||
|
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, {transferBarrier});
|
||||||
|
|
||||||
|
rotationVectorsImage->TransferToDeviceResource(cmdBuffer);
|
||||||
|
|
||||||
|
vk::ImageMemoryBarrier shaderReadBarrier{};
|
||||||
|
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, shaderReadBarrier);
|
||||||
|
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, { shaderReadBarrier });
|
||||||
|
|
||||||
|
|
||||||
// Get aligned size for buffer
|
// Get aligned size for buffer
|
||||||
uint32_t alignedSize = logicalDevice->PadSSBOSize(sizeof (SamplesAndKernel));
|
uint32_t alignedSize = logicalDevice->PadSSBOSize(sizeof (samples));
|
||||||
|
|
||||||
// Create buffer
|
// Create buffer
|
||||||
ssaoDataBuffer = logicalDevice->CreateBuffer(alignedSize, ssaoData.get(), alignedSize, vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, {});
|
ssaoDataBuffer = logicalDevice->CreateBuffer(alignedSize, samples.data(), alignedSize, vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, {});
|
||||||
|
|
||||||
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
|
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHSSAO::PrepareRotationVectorsVkData(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
{
|
||||||
|
SHImageViewDetails DETAILS =
|
||||||
|
{
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = vk::Format::eR32G32B32A32Sfloat,
|
||||||
|
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.mipLevelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1
|
||||||
|
};
|
||||||
|
rotationVectorsImageView = rotationVectorsImage->CreateImageView(logicalDevice, rotationVectorsImage, DETAILS);
|
||||||
|
|
||||||
|
SHVkSamplerParams samplerParams
|
||||||
|
{
|
||||||
|
.minFilter = vk::Filter::eNearest,
|
||||||
|
.magFilter = vk::Filter::eNearest,
|
||||||
|
.addressMode = vk::SamplerAddressMode::eRepeat,
|
||||||
|
.mipmapMode = vk::SamplerMipmapMode::eNearest,
|
||||||
|
.maxLod = 1u
|
||||||
|
};
|
||||||
|
|
||||||
|
rotationVectorsSampler = logicalDevice->CreateSampler(samplerParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVkDescriptorSetGroup::viewSamplerLayout SHSSAO::GetViewSamplerLayout(void) const noexcept
|
||||||
|
{
|
||||||
|
return std::make_tuple(rotationVectorsImageView, rotationVectorsSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
|
}
|
||||||
|
|
||||||
Handle<SHVkBuffer> SHSSAO::GetBuffer(void) const noexcept
|
Handle<SHVkBuffer> SHSSAO::GetBuffer(void) const noexcept
|
||||||
{
|
{
|
||||||
return ssaoDataBuffer;
|
return ssaoDataBuffer;
|
||||||
|
|
|
@ -3,39 +3,47 @@
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "Graphics/SHVulkanIncludes.h"
|
#include "Graphics/SHVulkanIncludes.h"
|
||||||
#include "Math/Vector/SHVec4.h"
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHVkBuffer;
|
class SHVkBuffer;
|
||||||
class SHVkLogicalDevice;
|
class SHVkLogicalDevice;
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
|
class SHVkImage;
|
||||||
|
class SHVkImageView;
|
||||||
|
class SHVkSampler;
|
||||||
|
|
||||||
class SHSSAO
|
class SHSSAO
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr uint32_t DESC_SET_BINDING = 0;
|
static constexpr uint32_t DESC_SET_BUFFER_BINDING = 0;
|
||||||
|
static constexpr uint32_t DESC_SET_IMAGE_BINDING = 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint32_t NUM_SAMPLES = 64;
|
static constexpr uint32_t NUM_SAMPLES = 64;
|
||||||
static constexpr uint32_t NUM_ROTATION_VECTORS = 16;
|
static constexpr uint32_t NUM_ROTATION_VECTORS_W = 4;
|
||||||
|
static constexpr uint32_t NUM_ROTATION_VECTORS_H = 4;
|
||||||
struct SamplesAndKernel
|
static constexpr uint32_t NUM_ROTATION_VECTORS = NUM_ROTATION_VECTORS_W * NUM_ROTATION_VECTORS_H;
|
||||||
{
|
|
||||||
//! distances from a pixel we want to sample
|
|
||||||
std::array<SHVec4, NUM_SAMPLES> samples;
|
|
||||||
|
|
||||||
std::array<SHVec4, NUM_ROTATION_VECTORS> rotatationVectors;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Samples and kernel on CPU side
|
//! distances from a pixel we want to sample
|
||||||
std::unique_ptr<SamplesAndKernel> ssaoData;
|
std::array<SHVec4, NUM_SAMPLES> samples;
|
||||||
|
|
||||||
//! For passing SSAO samples and kernel to GPU
|
//! For passing SSAO samples and kernel to GPU
|
||||||
Handle<SHVkBuffer> ssaoDataBuffer;
|
Handle<SHVkBuffer> ssaoDataBuffer;
|
||||||
|
|
||||||
|
std::array<SHVec4, NUM_ROTATION_VECTORS> rotationVectors;
|
||||||
|
|
||||||
|
Handle<SHVkImage> rotationVectorsImage;
|
||||||
|
Handle<SHVkImageView> rotationVectorsImageView;
|
||||||
|
Handle<SHVkSampler> rotationVectorsSampler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||||
|
void PrepareRotationVectorsVkData (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||||
|
SHVkDescriptorSetGroup::viewSamplerLayout GetViewSamplerLayout (void) const noexcept;
|
||||||
|
|
||||||
Handle<SHVkBuffer> GetBuffer (void) const noexcept;
|
Handle<SHVkBuffer> GetBuffer (void) const noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,4 +175,11 @@ namespace SHADE
|
||||||
computeResource->descSet->UpdateDescriptorSetBuffer(set, binding);
|
computeResource->descSet->UpdateDescriptorSetBuffer(set, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHRenderGraphNodeCompute::ModifyWriteDescImageComputeResource(uint32_t set, uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept
|
||||||
|
{
|
||||||
|
computeResource->descSet->ModifyWriteDescImage(set, binding, viewSamplerLayouts);
|
||||||
|
computeResource->descSet->UpdateDescriptorSetImages(set, binding);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
#include "Graphics/SHVulkanIncludes.h"
|
#include "Graphics/SHVulkanIncludes.h"
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -10,7 +11,6 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHVkPipeline;
|
class SHVkPipeline;
|
||||||
class SHVkDescriptorSetGroup;
|
|
||||||
class SHVkDescriptorPool;
|
class SHVkDescriptorPool;
|
||||||
class SHVkLogicalDevice;
|
class SHVkLogicalDevice;
|
||||||
class SHVkPipelineLayout;
|
class SHVkPipelineLayout;
|
||||||
|
@ -74,6 +74,8 @@ namespace SHADE
|
||||||
void SetDynamicOffsets (std::span<uint32_t> perFrameSizes) noexcept;
|
void SetDynamicOffsets (std::span<uint32_t> perFrameSizes) noexcept;
|
||||||
|
|
||||||
void ModifyWriteDescBufferComputeResource (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
void ModifyWriteDescBufferComputeResource (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||||
|
void ModifyWriteDescImageComputeResource(uint32_t set, uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept;
|
||||||
|
|
||||||
|
|
||||||
friend class SHRenderGraph;
|
friend class SHRenderGraph;
|
||||||
friend class SHRenderGraphNode;
|
friend class SHRenderGraphNode;
|
||||||
|
|
Loading…
Reference in New Issue