74 lines
2.3 KiB
GLSL
74 lines
2.3 KiB
GLSL
#version 450 core
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
|
|
#include "lib/common.glsl"
|
|
|
|
IN(0, vec2, texcoord)
|
|
OUT(0, float, ssao)
|
|
|
|
#define KERNEL_SIZE 32
|
|
layout (std140, binding = 0) uniform Params {
|
|
mat4 Projection;
|
|
vec4 Kernel[KERNEL_SIZE];
|
|
int Samples;
|
|
float Scale;
|
|
float Radius;
|
|
float Bias;
|
|
float Power;
|
|
};
|
|
|
|
SAMPLER(1, position)
|
|
SAMPLER(2, normal)
|
|
SAMPLER(3, noise)
|
|
|
|
void main()
|
|
{
|
|
vec2 noiseSize = vec2(textureSize(tex_noise, 0));
|
|
vec2 outputSize = vec2(textureSize(tex_position, 0)) / Scale;
|
|
vec2 noiseScale = outputSize / noiseSize;
|
|
|
|
// get input vectors from gbuffer & noise texture
|
|
vec3 fragPos = texture(tex_position, in_texcoord).xyz;
|
|
vec3 normalEncoded = texture(tex_normal, in_texcoord).xyz;
|
|
vec3 normal = unpack_normal(normalEncoded);
|
|
|
|
// discard gbuffer entries without normal data
|
|
if (normalEncoded == vec3(0)) {
|
|
out_ssao = 1;
|
|
return;
|
|
}
|
|
|
|
vec3 randomVec = texture(tex_noise, in_texcoord * noiseScale).xyz;
|
|
|
|
// create TBN change-of-basis matrix: from tangent-space to view-space
|
|
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
|
vec3 bitangent = cross(normal, tangent);
|
|
mat3 TBN = mat3(tangent, bitangent, normal);
|
|
|
|
// iterate over the sample kernel and calculate occlusion factor
|
|
float occlusion = 0.0;
|
|
for(int i = 0; i < Samples; ++i)
|
|
{
|
|
// get sample position
|
|
vec3 sampleVec = TBN * Kernel[i].xyz; // from tangent to view-space
|
|
sampleVec = fragPos + sampleVec * Radius;
|
|
|
|
// project sample position (to sample texture) (to get position on screen/texture)
|
|
vec4 offset = vec4(sampleVec, 1.0);
|
|
offset = Projection * offset; // from view to clip-space
|
|
offset.xyz /= offset.w; // perspective divide, clip -> NDC
|
|
offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0
|
|
|
|
// get sample depth - i.e. the Z component of the sampled position in view space
|
|
float sampleDepth = texture(tex_position, offset.xy).z;
|
|
|
|
// range check & accumulate
|
|
float rangeCheck = smoothstep(0.0, 1.0, Radius / abs(fragPos.z - sampleDepth));
|
|
occlusion += (sampleDepth <= sampleVec.z - Bias ? 1.0 : 0.0) * rangeCheck;
|
|
}
|
|
occlusion = 1.0 - (occlusion / Samples);
|
|
occlusion = pow(occlusion, Power);
|
|
|
|
out_ssao = occlusion;
|
|
}
|