Skip to content
Permalink
Browse files

Add Screen Space Ambient Occlusion

  • Loading branch information...
ForbodingAngel committed May 8, 2019
1 parent 11fbb1c commit 2e44ff06ee64a83dca36f9e8890577822e84a9bc

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,31 @@
#version 150 compatibility

uniform sampler2D tex;

uniform float offsets[###HALF_KERNEL_SIZE###];
uniform float weights[###HALF_KERNEL_SIZE###];

uniform vec2 dir;

uniform vec2 viewPortSize;

void main(void)
{
vec2 uv = gl_FragCoord.xy / viewPortSize;
vec4 acc = texture( tex, uv ) * weights[0];
float okCoords;

for (int i = 1; i < ###HALF_KERNEL_SIZE###; ++i) {
vec2 uvOff = offsets[i] * dir / viewPortSize;
vec2 uvP = uv + uvOff;
vec2 uvN = uv - uvOff;

okCoords = float( all(bvec4( greaterThanEqual(uvP, vec2(0.0)), lessThanEqual(uvP, vec2(1.0)) )) );
acc += texture( tex, uvP ) * weights[i] * okCoords;

okCoords = float( all(bvec4( greaterThanEqual(uvN, vec2(0.0)), lessThanEqual(uvN, vec2(1.0)) )) );
acc += texture( tex, uvN ) * weights[i] * okCoords;
}

gl_FragColor = acc;
}
@@ -0,0 +1,5 @@
#version 150 compatibility

void main() {
gl_Position = gl_Vertex;
}
@@ -0,0 +1,63 @@
#version 150 compatibility

#define DEPTH_CLIP01 ###DEPTH_CLIP01###

uniform sampler2D modelDepthTex;
uniform sampler2D mapDepthTex;

uniform sampler2D modelNormalTex;
uniform sampler2D mapNormalTex;

uniform vec2 viewPortSize;

uniform mat4 invProjMatrix;
uniform mat4 viewMatrix;

#define NORM2SNORM(value) (value * 2.0 - 1.0)
#define SNORM2NORM(value) (value * 0.5 + 0.5)

// Calculate out of the fragment in screen space the view space position.
vec4 GetViewPos(vec2 texCoord, float sampledDepth) {
vec4 projPosition = vec4(0.0, 0.0, 0.0, 1.0);

//texture space [0;1] to NDC space [-1;1]
#if DEPTH_CLIP01
//don't transform depth as it's in the same [0;1] space
projPosition.xyz = vec3(NORM2SNORM(texCoord), sampledDepth);
#else
projPosition.xyz = NORM2SNORM(vec3(texCoord, sampledDepth));
#endif

vec4 viewPosition = invProjMatrix * projPosition;
viewPosition /= viewPosition.w;

return viewPosition;
}

void main() {
vec2 uv = gl_FragCoord.xy / viewPortSize;

float modelDepth = texelFetch(modelDepthTex, ivec2(gl_FragCoord.xy), 0).r;
float mapDepth = texelFetch(mapDepthTex, ivec2(gl_FragCoord.xy), 0).r;

float modelOccludesMap = float(modelDepth < mapDepth);
float depth = mix(mapDepth, modelDepth, modelOccludesMap);

vec4 viewPosition = GetViewPos(uv, depth);

vec3 modelNormal = texture(modelNormalTex, uv).rgb;
vec3 mapNormal = texture(mapNormalTex, uv).rgb;

vec3 viewNormal = mix(mapNormal, modelNormal, modelOccludesMap);
float validNormal = float(length(viewNormal) > 0.2); //empty spaces in g-buffer will have vec3(0.0) normals

viewNormal = NORM2SNORM(viewNormal);
viewNormal = normalize(viewNormal);
viewNormal = vec3(viewMatrix * vec4(viewNormal, 0.0)); //transform world-->view space

// MRT output:
//[0] = gbuffFuseViewPosTex
//[1] = gbuffFuseViewNormalTex
gl_FragData[0].xyz = viewPosition.xyz;
gl_FragData[1].xyz = mix( vec3(0.0), viewNormal.xyz, vec3(validNormal) );
}
@@ -0,0 +1,5 @@
#version 150 compatibility

void main() {
gl_Position = gl_Vertex;
}
@@ -0,0 +1,132 @@
#version 150 compatibility

uniform sampler2D viewPosTex;
uniform sampler2D viewNormalTex;

uniform vec2 viewPortSize;

uniform mat4 projMatrix;

#define NORM2SNORM(value) (value * 2.0 - 1.0)
#define SNORM2NORM(value) (value * 0.5 + 0.5)

vec3 hash33(vec3 p) {
const uint k = 1103515245U;

uvec3 x = uvec3(p);

x = ((x >> 8U) ^ x.yzx) * k;
x = ((x >> 8U) ^ x.yzx) * k;
x = ((x >> 8U) ^ x.yzx) * k;

return vec3(x) * (1.0 / float(0xFFFFFFFFU));
}

vec3 hash32(vec2 p) {
const uint k = 1103515245U;

uvec3 x = uvec3(p.xy, 0U);
x.z = (x.y >> 1U) ^ x.x;

x = ((x >> 8U) ^ x.yzx) * k;
x = ((x >> 8U) ^ x.yzx) * k;
x = ((x >> 8U) ^ x.yzx) * k;

return vec3(x) * (1.0 / float(0xFFFFFFFFU));
}

//----------------------------------------------------------------------------------------

#define SSAO_KERNEL_SIZE ###SSAO_KERNEL_SIZE###

#define SSAO_RADIUS ###SSAO_RADIUS###
#define SSAO_MIN 0.1 * SSAO_RADIUS
#define SSAO_MAX 1.0 * SSAO_RADIUS

#define SSAO_FADE_DIST 1000.0

#define SSAO_ALPHA_POW 1.5
#define SSAO_COLOR vec3(0.5)

//----------------------------------------------------------------------------------------

flat in vec3 samplingKernel[SSAO_KERNEL_SIZE];

// generally follow https://github.com/McNopper/OpenGL/blob/master/Example28/shader/ssao.frag.glsl
void main() {
vec2 uv = gl_FragCoord.xy / viewPortSize;

vec4 viewPosition = vec4( texture(viewPosTex, uv).xyz, 1.0 );
vec3 viewNormal = texture(viewNormalTex, uv).xyz;

gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0);

if ( dot(viewNormal, viewNormal) > 0.0 ) {
// Calculate the rotation matrix for the kernel.
vec3 randomVector = normalize( NORM2SNORM(hash32(gl_FragCoord.xy)) );

// Using Gram-Schmidt process to get an orthogonal vector to the normal vector.
// The resulting tangent is on the same plane as the random and normal vector.
// see http://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
// Note: No division by <u,u> needed, as this is for normal vectors 1.
vec3 viewTangent = normalize(randomVector - dot(randomVector, viewNormal) * viewNormal);

vec3 viewBitangent = cross(viewNormal, viewTangent);

// Final matrix to reorient the kernel depending on the normal and the random vector.
// TBN matrix. Transforms from tangent space to view space
mat3 kernelMatrix = mat3(viewTangent, viewBitangent, viewNormal);

// Go through the kernel samples and create occlusion factor.
float occlusion = 0.0;
//float occlusionSamples = 0.0;

float fragDistFactor = 1.0 - smoothstep( SSAO_FADE_DIST, 2.0 * SSAO_FADE_DIST, -viewPosition.z );
fragDistFactor = 1.0;

for (int i = 0; i < SSAO_KERNEL_SIZE; ++i) {
// Reorient sample vector in view space ...
vec3 viewSampleVector = kernelMatrix * samplingKernel[i];

// ... and calculate sample point.
vec4 viewTestPosition = viewPosition + SSAO_RADIUS * vec4(viewSampleVector, 0.0);

// projection
vec4 ndcTestPosition = projMatrix * viewTestPosition;
// perspecitive division
ndcTestPosition /= ndcTestPosition.w;

// [-1;1] to [0;1]
vec2 texSampingPoint = SNORM2NORM(ndcTestPosition.xy);

float sampleProjDistanceFactor = smoothstep(0.0, 3.0, distance(texSampingPoint * viewPortSize, gl_FragCoord.xy));

// Get sample viewPos from the viewPosTex texture
vec3 viewPositionSampled = texture(viewPosTex, texSampingPoint).xyz;

float delta = viewPositionSampled.z - viewTestPosition.z;

float occlusionCondition = float(delta >= SSAO_MIN && delta <= SSAO_MAX);

occlusion += occlusionCondition * fragDistFactor * sampleProjDistanceFactor;
}

// No occlusion gets white, full occlusion gets black.
occlusion = 1.0 - occlusion / float(SSAO_KERNEL_SIZE);

float occlusionAlpha = occlusion;
occlusionAlpha = pow(occlusionAlpha, SSAO_ALPHA_POW);

occlusionAlpha = clamp(1.0 - occlusionAlpha, 0.0, 1.0);
//occlusionAlpha = 1.0;

gl_FragColor = vec4(SSAO_COLOR * vec3(occlusion), occlusionAlpha);
//gl_FragColor.rgba = vec4(fragDistFactor);
//gl_FragColor = vec4(0.0);
//gl_FragColor.xyz = viewNormal.xyz;
//gl_FragColor.xyz = vec3(-viewPosition.z / 8000.0);
//gl_FragColor.xyz = vec3(viewPosition.z);
}
//gl_FragColor.rgba = vec4(1.0);
//gl_FragColor.xyz = viewNormal.xyz;
}
@@ -0,0 +1,35 @@
#version 150 compatibility

#define NORM2SNORM(value) (value * 2.0 - 1.0)
#define SNORM2NORM(value) (value * 0.5 + 0.5)

vec3 hash31(float p) {
uint n = uint(p);

n = (n << 13U) ^ n;
n = n * (n * n * 15731U + 789221U) + 1376312589U;
uvec3 k = n * uvec3(n, n * 16807U, n * 48271U);
return vec3( k & uvec3(0x7FFFFFFFU) ) / float(0x7FFFFFFF);
}

//----------------------------------------------------------------------------------------

#define SSAO_KERNEL_SIZE ###SSAO_KERNEL_SIZE###

//----------------------------------------------------------------------------------------

flat out vec3 samplingKernel[SSAO_KERNEL_SIZE];

void main() {
gl_Position = gl_Vertex;

for (int i = 0; i < SSAO_KERNEL_SIZE; i++) {
vec3 tmp = hash31( float(i) );
tmp.xy = NORM2SNORM(tmp.xy);
tmp = normalize(tmp);
float scale = float(i)/float(SSAO_KERNEL_SIZE);
scale = clamp(scale * scale, 0.1, 1.0);
tmp *= scale;
samplingKernel[i] = tmp;
}
}
Oops, something went wrong.

0 comments on commit 2e44ff0

Please sign in to comment.
You can’t perform that action at this time.