154 lines
No EOL
4.9 KiB
GLSL
154 lines
No EOL
4.9 KiB
GLSL
#include "../math/saturate.glsl"
|
|
#include "../space/linearizeDepth.glsl"
|
|
#include "../space/depth2viewZ.glsl"
|
|
#include "../sampler.glsl"
|
|
#include "../generative/random.glsl"
|
|
|
|
/*
|
|
contributors: Patricio Gonzalez Vivo
|
|
description: ScreenSpace Ambient Occlusion
|
|
use: <float> ssao(<SAMPLER_TYPE> texPosition, <SAMPLER_TYPE> texNormal, vec2 <st> [, <float> radius, float <bias>])
|
|
options:
|
|
- SSAO_SAMPLES_NUM: number of half-sphere offsets samples
|
|
- SSAO_SAMPLES_ARRAY: array of weighted vec3 half-sphere offsets
|
|
- SSAO_NOISE_NUM: number of vec3 noise offsets
|
|
- SSAO_NOISE_ARRAY: array of vec3 noise offsets
|
|
- SSAO_NOISE2_FNC(ST): (random2(ST * 100.) * 0.1)
|
|
- SSAO_NOISE3_FNC(POS): (random3(POS) * 0.3)
|
|
- CAMERA_PROJECTION_MATRIX: camera projection mat4 matrix
|
|
- CAMERA_NEAR_CLIP: required for depth only SSAO
|
|
- CAMERA_FAR_CLIP: required for depth only SSAO
|
|
- SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))
|
|
license:
|
|
- Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0
|
|
- Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license
|
|
*/
|
|
|
|
#ifndef SSAO_SAMPLES_NUM
|
|
#define SSAO_SAMPLES_NUM 8
|
|
#endif
|
|
|
|
#ifndef SSAO_SAMPLES_ARRAY
|
|
#if defined(GLSLVIEWER)
|
|
#define SSAO_SAMPLES_ARRAY u_ssaoSamples
|
|
uniform vec3 u_ssaoSamples[SSAO_SAMPLES_NUM];
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef SSAO_NOISE_NUM
|
|
#define SSAO_NOISE_NUM 4
|
|
#endif
|
|
|
|
#ifndef SSAO_NOISE_ARRAY
|
|
#if defined(GLSLVIEWER)
|
|
#define SSAO_NOISE_ARRAY u_ssaoNoise
|
|
uniform vec3 u_ssaoNoise[SSAO_NOISE_NUM];
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef CAMERA_PROJECTION_MATRIX
|
|
#if defined(GLSLVIEWER)
|
|
#define CAMERA_PROJECTION_MATRIX u_projectionMatrix
|
|
#else
|
|
#define CAMERA_PROJECTION_MATRIX u_projection
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef SSAO_NOISE2_FNC
|
|
#define SSAO_NOISE2_FNC(ST) random2(ST)
|
|
#endif
|
|
|
|
#ifndef SSAO_NOISE3_FNC
|
|
#define SSAO_NOISE3_FNC(POS) random3(POS)
|
|
#endif
|
|
|
|
#ifndef SSAO_DEPTH_BIAS
|
|
#define SSAO_DEPTH_BIAS 0.05
|
|
#endif
|
|
|
|
#ifndef FNC_SSAO
|
|
#define FNC_SSAO
|
|
|
|
#if defined(CAMERA_NEAR_CLIP) && defined(CAMERA_FAR_CLIP)
|
|
|
|
float ssao(SAMPLER_TYPE texDepth, vec2 st, vec2 pixel, float radius) {
|
|
|
|
#if defined(SSAO_NOISE_ARRAY)
|
|
float noiseS = sqrt(float(SSAO_NOISE_NUM));
|
|
int noiseX = int( mod(gl_FragCoord.x - 0.5, noiseS) );
|
|
int noiseY = int( mod(gl_FragCoord.y - 0.5, noiseS) );
|
|
vec2 noise = SSAO_NOISE_ARRAY[noiseX + noiseY * int(noiseS)].xy;
|
|
#else
|
|
vec2 noise = SSAO_NOISE2_FNC( st );
|
|
#endif
|
|
noise *= 0.1;
|
|
|
|
float depth = depth2viewZ( SAMPLER_FNC( texDepth, st ).r ) + SSAO_DEPTH_BIAS * 0.5;
|
|
float ao = 0.0;
|
|
|
|
// if (depth < 0.99)
|
|
{
|
|
float w = pixel.x / depth + noise.x;
|
|
float h = pixel.y / depth + noise.y;
|
|
|
|
float dz = 1.0 / float( SSAO_SAMPLES_NUM );
|
|
float l = 0.0;
|
|
float z = 1.0 - dz * 0.5;
|
|
|
|
for ( int i = 0; i < SSAO_SAMPLES_NUM; i ++ ) {
|
|
float r = sqrt( 1.0 - z );
|
|
float pw = cos( l ) * r;
|
|
float ph = sin( l ) * r;
|
|
vec2 vv = radius * vec2( pw * w, ph * h);
|
|
ao += ( step( depth2viewZ( SAMPLER_FNC( texDepth, st + vv).r ), depth) +
|
|
step( depth2viewZ( SAMPLER_FNC( texDepth, st - vv).r ), depth) ) * 0.5;
|
|
z = z - dz;
|
|
l = l + 2.399963229728653;
|
|
}
|
|
ao = 1.0 - ao * dz;
|
|
ao = saturate( 1.98 * ( 1.0 - ao ) );
|
|
}
|
|
return ao;
|
|
}
|
|
#endif
|
|
|
|
#if defined(SSAO_SAMPLES_ARRAY)
|
|
|
|
float ssao(SAMPLER_TYPE texPosition, SAMPLER_TYPE texNormal, vec2 st, float radius) {
|
|
vec4 position = SAMPLER_FNC(texPosition, st);
|
|
vec3 normal = SAMPLER_FNC(texNormal, st).rgb;
|
|
|
|
#if defined(SSAO_NOISE_ARRAY)
|
|
float noiseS = sqrt(float(SSAO_NOISE_NUM));
|
|
int noiseX = int( mod(gl_FragCoord.x - 0.5, noiseS) );
|
|
int noiseY = int( mod(gl_FragCoord.y - 0.5, noiseS) );
|
|
vec3 noise = SSAO_NOISE_ARRAY[noiseX + noiseY * int(noiseS)];
|
|
#else
|
|
vec3 noise = SSAO_NOISE3_FNC( position.xyz );
|
|
#endif
|
|
|
|
vec3 tangent = normalize(noise - normal * dot(noise, normal));
|
|
vec3 binormal = cross(normal, tangent);
|
|
mat3 tbn = mat3(tangent, binormal, normal);
|
|
|
|
float occlusion = 0.0;
|
|
for (int i = 0; i < SSAO_SAMPLES_NUM; ++i) {
|
|
vec3 samplePosition = tbn * SSAO_SAMPLES_ARRAY[i];
|
|
samplePosition = position.xyz + samplePosition * radius;
|
|
|
|
vec4 offsetUV = vec4(samplePosition, 1.0);
|
|
offsetUV = CAMERA_PROJECTION_MATRIX * offsetUV;
|
|
offsetUV.xy /= offsetUV.w;
|
|
offsetUV.xy = offsetUV.xy * 0.5 + 0.5;
|
|
|
|
float sampleDepth = SAMPLER_FNC(texPosition, offsetUV.xy).z;
|
|
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth));
|
|
occlusion += (sampleDepth >= samplePosition.z + SSAO_DEPTH_BIAS ? 1.0 : 0.0) * rangeCheck;
|
|
}
|
|
|
|
occlusion /= float(SSAO_SAMPLES_NUM);
|
|
return 1.0-occlusion;
|
|
}
|
|
#endif
|
|
|
|
#endif |