Skip to content

Commit 317c7a4

Browse files
committed
Add the very low and ultra quality.
The VERY_LOW quality shader now only takes the midpoint plus 2 extra samples. The High and ULTRA quality settings now have a shader that samples in 3 or 4 rings.
1 parent db70107 commit 317c7a4

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

drivers/gles3/effects/post_effects.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,14 @@ void PostEffects::post_copy(
107107
flags |= PostShaderGLES3::USE_GLOW;
108108
}
109109
if (p_ssao_enabled) {
110-
if (p_ssao_quality_level <= RS::ENV_SSAO_QUALITY_LOW) {
110+
if (p_ssao_quality_level == RS::ENV_SSAO_QUALITY_VERY_LOW) {
111+
flags |= PostShaderGLES3::USE_SSAO_ABYSS;
112+
} else if (p_ssao_quality_level == RS::ENV_SSAO_QUALITY_LOW) {
111113
flags |= PostShaderGLES3::USE_SSAO_LOW;
112-
} else if (p_ssao_quality_level >= RS::ENV_SSAO_QUALITY_HIGH) {
114+
} else if (p_ssao_quality_level == RS::ENV_SSAO_QUALITY_HIGH) {
113115
flags |= PostShaderGLES3::USE_SSAO_HIGH;
116+
} else if (p_ssao_quality_level == RS::ENV_SSAO_QUALITY_ULTRA) {
117+
flags |= PostShaderGLES3::USE_SSAO_MEGA;
114118
} else {
115119
flags |= PostShaderGLES3::USE_SSAO_MED;
116120
}

drivers/gles3/shaders/effects/post.glsl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ USE_LUMINANCE_MULTIPLIER = false
1010
USE_BCS = false
1111
USE_COLOR_CORRECTION = false
1212
USE_1D_LUT = false
13+
USE_SSAO_ABYSS = false
1314
USE_SSAO_LOW = false
1415
USE_SSAO_MED = false
1516
USE_SSAO_HIGH = false
17+
USE_SSAO_MEGA = false
1618

1719
#[vertex]
1820
layout(location = 0) in vec2 vertex_attrib;
@@ -94,7 +96,8 @@ vec3 apply_bcs(vec3 color) {
9496
}
9597
#endif
9698

97-
#if defined(USE_SSAO_LOW) || defined(USE_SSAO_MED) || defined(USE_SSAO_HIGH)
99+
#if defined(USE_SSAO_ABYSS) || defined(USE_SSAO_LOW) || defined(USE_SSAO_MED) || defined(USE_SSAO_HIGH) || defined(USE_SSAO_MEGA)
100+
#define USE_SOME_SSAO
98101
uniform float ssao_intensity;
99102
uniform float ssao_radius_frac;
100103
uniform vec2 ssao_prn_UV;
@@ -104,8 +107,17 @@ uniform sampler2DArray depth_buffer_array; // texunit:3
104107
#else
105108
uniform sampler2D depth_buffer; // texunit:3
106109
#endif
110+
#if defined(USE_SSAO_ABYSS)
111+
// Use the tiny 2-sample version.
112+
#include "../s4ao_micro_inc.glsl"
113+
#elif defined(USE_SSAO_HIGH) || defined(USE_SSAO_MEGA)
114+
// Use the rings version for the higher qualities.
115+
#include "../s4ao_mega_inc.glsl"
116+
#else
117+
// Use the more generic NxN grid version.
107118
#include "../s4ao_inc.glsl"
108119
#endif
120+
#endif
109121

110122
in vec2 uv_interp;
111123

@@ -134,7 +146,7 @@ void main() {
134146

135147
color.rgb = srgb_to_linear(color.rgb);
136148

137-
#if defined(USE_SSAO_LOW) || defined(USE_SSAO_MED) || defined(USE_SSAO_HIGH)
149+
#if defined(USE_SOME_SSAO)
138150
// Putting SSAO after the conversion to linear color, though it might be better before the glow.
139151
color.rgb *= s4ao(uv_interp); // The USE_SSAO_X controls the number of samples.
140152
#endif
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// S4AO (Stupid Simple Screen Space Ambient Occlusion) - Jonathan Dummer (O1S)
2+
// The mega version uses N concentric rings of samples.
3+
4+
#if defined(USE_SSAO_MEGA)
5+
const int rings = 4; // Start with the outer ring.
6+
const int samps[] = int[](24, 18, 12, 6); // ( 9, 6, 3 ) is a minimum, but I want better.
7+
#else
8+
const int rings = 3; // Start with the outer ring.
9+
const int samps[] = int[](15, 10, 5, 1); // ( 9, 6, 3 ) is a minimum, but I want better.
10+
#endif
11+
const float average_samples = 1.0 / float(samps[0] + samps[1] * int(rings > 1) + samps[2] * int(rings > 2) + samps[3] * int(rings > 3));
12+
const float ssao_falloff_frac = 0.25;
13+
// Perform the SSAO.
14+
float s4ao(vec2 UV) {
15+
#ifdef USE_MULTIVIEW
16+
float depth = texture(depth_buffer_array, vec3(UV, view)).r;
17+
#else
18+
float depth = texture(depth_buffer, UV).r;
19+
#endif
20+
float inv_falloff = 1.0f / max(1e-4f, depth * ssao_falloff_frac);
21+
// Random 2D rotation per pixel (0..1 -> parabola approximating a 180 deg arc)
22+
float r01 = fract(dot(UV, ssao_prn_UV));
23+
vec2 rcos = vec2(r01 - 0.5f, 2.0f * (r01 - r01 * r01)) * (2.0f * depth * ssao_radius_frac); // 180 degrees.
24+
vec2 rsin = rcos.yx * vec2(-1, 1); // Perpendicular to the random cosine vector.
25+
// Grab the samples and determine the occlusion.
26+
float occlusion = 0.0f;
27+
float ring_shrink = 0.75f; // Shrink every ring.
28+
for (int r = 0; r < rings; ++r) {
29+
float dt = (6.283185307f) / float(samps[r]);
30+
float t = float(r & 1) * 0.5f * dt;
31+
for (int s = 0; s < samps[r]; ++s) {
32+
vec2 duv = cos(t) * rcos + sin(t) * rsin;
33+
#ifdef USE_MULTIVIEW
34+
float dz = texture(depth_buffer_array, vec3(UV + duv, view)).r - depth;
35+
#else
36+
float dz = texture(depth_buffer, UV + duv).r - depth;
37+
#endif
38+
// How 'directly overhead' is it? Factor in the falloff depth.
39+
occlusion += normalize(vec3(duv, dz)).z * smoothstep(1.0f, 0.0f, dz * inv_falloff);
40+
t += dt;
41+
}
42+
// The next ring will be smaller.
43+
rcos *= ring_shrink;
44+
rsin *= ring_shrink;
45+
}
46+
// Adjust the occlusion for intensity, and # samples.
47+
occlusion *= ssao_intensity * average_samples;
48+
occlusion = 1.0f - clamp(occlusion, 0.0f, 1.0f);
49+
return occlusion * occlusion;
50+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// S4AO (Stupid Simple Screen Space Ambient Occlusion) - Jonathan Dummer (O1S)
2+
// This micro version uses only 3 depth samples, the midpoint and a randomly-rotated, balanced pair.
3+
4+
const mediump float ssao_falloff_frac = 0.25;
5+
// Perform the SSAO.
6+
float s4ao(vec2 UV) {
7+
#ifdef USE_MULTIVIEW
8+
mediump float depth = texture(depth_buffer_array, vec3(UV, view)).r;
9+
#else
10+
mediump float depth = texture(depth_buffer, UV).r;
11+
#endif
12+
mediump float inv_falloff = 1.0f / max(1e-4f, depth * ssao_falloff_frac);
13+
// Random 2D rotation per pixel (0..1 -> parabola approximating a 180 deg arc)
14+
mediump float r01 = fract(dot(UV, ssao_prn_UV));
15+
mediump vec2 duv = vec2(r01 - 0.5f, 2.0f * (r01 - r01 * r01)) * (2.0f * depth * ssao_radius_frac); // 180 degrees.
16+
// Grab the samples and determine the occlusion.
17+
mediump float occlusion = 0.0f;
18+
for (int s = 0; s < 2; ++s) {
19+
#ifdef USE_MULTIVIEW
20+
mediump float dz = texture(depth_buffer_array, vec3(UV + duv, view)).r - depth;
21+
#else
22+
mediump float dz = texture(depth_buffer, UV + duv).r - depth;
23+
#endif
24+
// How 'directly overhead' is it? Factor in the falloff depth.
25+
occlusion += normalize(vec3(duv, dz)).z * mix(1.0f, 0.0f, dz * inv_falloff);
26+
// Mirror the next sample.
27+
duv = -duv;
28+
}
29+
// Adjust the occlusion for intensity, and # samples.
30+
occlusion = 1.0f - clamp(occlusion * 0.5f * ssao_intensity, 0.0f, 1.0f);
31+
return occlusion * occlusion;
32+
}

0 commit comments

Comments
 (0)