1

I was trying to implement the Crytek SSAO technique based on a shader shown in the Appendix of the following paper:

Shader from paper: enter image description here

However, when implementing and running the shader, it kept giving me this graining look and I cannot seem to identify what might have caused this particular issue.

My implementation of the shader:

#version 450

layout(binding = 3) uniform sampler2D texNoise;
layout(binding = 6) uniform sampler2D depthMap;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 uvCoords;


layout(binding = 5) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
    float time;
}camera;


layout(binding = 4) uniform KernelSample {
    vec3 samples[64];
    mat4 projection;
    vec4 camera_eye;
    vec4 camera_direction;
    float z_far;
}kernelsamples;

int kernelSize = 64;

layout(location = 0) out vec4 outColor;

vec4 ambient_occlusion;

float ec_depth(in vec2 tc)
{
    float buffer_z = texture(depthMap, tc).x;
    return camera.proj[3][2] / (-2.0 * buffer_z + 1.0 - camera.proj[2][2]);
}

const vec2 window = vec2(2560.0, 1440.0);

void main()

{

    vec2 tc_depths = gl_FragCoord.xy / uvCoords;

    float ec_depth_negated = -ec_depth(tc_depths);
    vec3 wc_positions = kernelsamples.camera_eye.xyz + kernelsample.camera_direction * ec_depth_negated / kernelsamples.z_far;

    ambient_occlusion.a = 0.0f;
    const float radius = 10.0f;
    const int samples = 64;

    float projection_scale_xy = 1.0 / ec_depth_negated;
    float projection_scale_z = 100.0 / kernelsamples.z_far * projection_scale_xy;

    float scene_depth = texture(depthMap, tc_depths).x;

    vec2 inverted_random_texture_size = 1.0 / vec2(textureSize(texNoise, 0));
    vec2 tc_random_texture = gl_FragCoord.xy * inverted_random_texture_size;

    vec3 random_direction = texture(texNoise, tc_random_texture).xyz;
    random_direction = normalize(random_direction * 2.0 - 1.0);

    for(int i = 0; i < samples; i++)
    {
        vec3 sample_random_direction = texture(texNoise, vec2(float(i) * 
        inverted_random_texture_size.x, float(i / textureSize(texNoise, 0).x) *
        inverted_random_texture_size.y)).xyz;
        sample_random_direction = sample_random_direction * 2.0 - 1.0;
        sample_random_direction = reflect(sample_random_direction, random_direction);

        vec3 tc_sample_pos = vec3(tc_depths.xy, scene_depth) 
                 + vec3(sample_random_direction.xy * projection_scale_xy,
                     sample_random_direction.z * scene_depth * projection_scale_z) * radius;

        float sample_depth = texture(depthMap, tc_sample_pos.xy).x;

        ambient_occlusion.a += float(sample_depth > tc_sample_pos.z);
    }

    ambient_occlusion.a /= float(kernelSize);

    outColor = ambient_occlusion;

}

C++

// Projection
 ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / 
(float)swapChainExtent.height, 0.1f, 1000.0f);
ubo.proj[1][1] *= -1;

KernelSample ks{}; 
.....
ks.cameraEye = glm::vec4(cameraPosition, 0.0f);
ks.cameraDirection = glm::vec4(cameraPosition + cameraCenter, 1.0f);

RenderPass

VkAttachmentDescription colorAttachment{};
colorAttachment.format = VK_FORMAT_R16_SFLOAT;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

VkAttachmentDescription depthAttachment = {};
depthAttachment.format = format;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentReference colorAttatchmentRef{};
colorAttatchmentRef.attachment = 0;
colorAttatchmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttatchmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;

VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

std::array<VkAttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };

VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;

Result enter image description here

SSAO shader output enter image description here

Krellex
  • 613
  • 2
  • 7
  • 20
  • Please also post the code for your attachment setup and/or synchronization for the attachment writes and reads. This looks like a typical wrong store/load ops or sync error. – Sascha Willems Oct 27 '21 at 17:31
  • Thanks for the suggestion. I have updated the post. – Krellex Oct 27 '21 at 18:10

0 Answers0