SSAO(4.3+)

Custom implementation of SSAO

Apply this shader to a quad, which is attached to the camera.
Add colorful screenshot as the “ssao_noise”.

Reference: https://learnopengl.com/index.php?p=Advanced-Lighting/SSAO

It would be better to implement this shader as a CompositorEffect, so it would be much more optimized.

The rough process would be as follows:
1. calculate AmbientOcclusion
2. blur in x-direction
3. blur in y-direction

Shader code
shader_type spatial;
render_mode unshaded, depth_draw_never;
const int kernelSize = 16;
const vec3 kernel[16] = {
	vec3(0.019026, 0.014279, 0.010519),
	vec3(-0.024865, 0.007903, 0.064579),
	vec3(-0.019492, 0.042650, 0.017825),
	vec3(0.026718, -0.026148, 0.014359),
	vec3(-0.053264, -0.057006, 0.091722),
	vec3(0.056508, -0.080027, 0.052389),
	vec3(-0.114437, 0.013222, 0.105258),
	vec3(0.084779, -0.132078, 0.057769),
	vec3(-0.013898, -0.089416, 0.171408),
	vec3(-0.131400, -0.059863, 0.038088),
	vec3(-0.009884, 0.009850, 0.001457),
	vec3(-0.010069, -0.031745, 0.012010),
	vec3(0.335164, 0.352856, 0.006707),
	vec3(0.348525, 0.232004, 0.126843),
	vec3(0.415091, 0.146300, 0.212393),
	vec3(0.143938, 0.040199, 0.314998)
};

uniform float radius: hint_range(0.0, 5.0) = 0.5;
uniform float bias: hint_range(0.0, 1.0) = 0.025;

uniform sampler2D SCREEN_TEXTURE: hint_screen_texture, source_color, repeat_disable;
uniform sampler2D DEPTH_TEXTURE: hint_depth_texture, repeat_disable, filter_nearest;
uniform sampler2D NORMAL_ROUGHNESS_TEXTURE: hint_normal_roughness_texture, source_color, repeat_disable, filter_nearest;
uniform sampler2D SSAO_NOISE: filter_nearest, repeat_enable, source_color;



float get_depth(vec2 uv, mat4 inv_proj) {
	float depth = texture(DEPTH_TEXTURE, uv).r;
	float linear_depth = 1.0 / (depth * inv_proj[2].w + inv_proj[3].w);
	return linear_depth;
}

vec3 get_position(vec2 uv, mat4 inv_proj_mat) {
	vec4 clipSpacePosition = vec4(uv * 2.0 - 1.0, texture(DEPTH_TEXTURE, uv).r, 1.0);
	vec4 viewSpacePosition = inv_proj_mat * clipSpacePosition;
	viewSpacePosition /= viewSpacePosition.w;
	return viewSpacePosition.xyz;
}

vec3 get_normal(vec2 uv) {
	vec3 normal = texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb;
	return (normal - 0.5) * 2.0;
}

void fragment() {
	const vec2 noiseScale = VIEWPORT_SIZE/4.0;
	float occlusionSum = 0.0;
	
	for (int x=-2; x<2; x++) {
		for (int y=-2; y<2; y++) {
			vec2 uv = SCREEN_UV + vec2(float(x),float(y)) / VIEWPORT_SIZE;
			vec3 fragPos = get_position(uv, INV_PROJECTION_MATRIX);
			vec3 normal = texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb;
			vec3 randomVec = texture(SSAO_NOISE, uv * noiseScale).xyz;
			
			vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
			vec3 bitangent = cross(normal, tangent);
			mat3 TBN = mat3(tangent, bitangent, normal);
			
			float occlusion = 0.0;
			
			for(int i=0; i < kernelSize; i++) {
				// get sample position
				vec3 sample = TBN * kernel[i];
				sample = fragPos + sample * radius;
				
				vec4 offset = vec4(sample, 1.0);
				offset = PROJECTION_MATRIX * offset;
				offset.xyz /= offset.w;
				offset.xyz = offset.xyz * 0.5 + 0.5;
				
				float sampleDepth = get_position(offset.xy, INV_PROJECTION_MATRIX).z;
				float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth));
				occlusion += (sampleDepth >= sample.z + bias ? 1.0 : 0.0) * rangeCheck;
			}
			occlusion /= float(kernelSize);
			occlusionSum += occlusion;
		}
	}
	
	
	ALBEDO = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
	ALBEDO *= 1.0 - vec3(occlusionSum / 16.0);
}
Tags
3d, ambien occlusion, screen-space, ScreenSpace, SSAO
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Firerabbit

View-MatCap

Terrain Mesh Blending with Dithering

Vector Sprite Upscaling Mix Colors

guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jooio
Jooio
1 year ago

Not so useless if it worked in compatibility mode

Melol
Melol
5 months ago
Reply to  Jooio

Remove the hint “hint_normal_roughness_texture”