rev: 21c5e6d2f665d0e8b4ff917a51b664c895dab2ed tukan/tukan/ssao.sc -rw-r--r-- 2.9 KiB View raw Log this file
21c5e6d2f665 — Leonard Ritter * renamed project from Liminal to Tukan 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using import .hash
using import glm

let SAMPLE_KERNEL_COUNT =
    match 0
        0 8
        1 16
        2 32
        else
            compiler-error! "select 0-2"

let H_SCALE = (/ SAMPLE_KERNEL_COUNT)
let RADIUS = 0.7

let FIB_INCR = (pi * (3.0 - (sqrt 5.0)))

fn fibonacci_point (index seed)
    "vec3 <- (i32 f32)"
    let numsamplesf = (f32 SAMPLE_KERNEL_COUNT)
    let rnd = (seed * numsamplesf)
    let samplef = (f32 index)
    let phi = (((samplef + rnd) % numsamplesf) * FIB_INCR)
    let cosTheta = (1.0 - (H_SCALE * (samplef - 0.5)))
    let sinTheta = (sqrt (1.0 - cosTheta * cosTheta))
    vec3
        (cos phi) * sinTheta
        (sin phi) * sinTheta
        cosTheta

fn hemisphere_sample_uniform (u v)
    "vec3 <- (f32 f32)"
    let phi = (v * 2.0 * pi)
    let cosTheta = (1.0 - u)
    let sinTheta = (sqrt (1.0 - cosTheta * cosTheta))
    vec3
        (cos phi) * sinTheta
        (sin phi) * sinTheta
        cosTheta

fn hemisphere_sample_cos (u v)
    "vec3 <- (f32 f32)"
    let phi = (v * 2.0 * pi)
    let cosTheta = (sqrt (1.0 - u))
    var sinTheta = (sqrt (1.0 - cosTheta * cosTheta))
    vec3
        (cos phi) * sinTheta
        (sin phi) * sinTheta
        cosTheta

fn SSAO (opts...)
    let radius =
        do
            let x = (va@ 'radius opts...)
            if (none? x) RADIUS
            else x

    # sample_depth (vp : vec3) -> f32
    # convert vp (viewspace) to ndc, offset by * 0.5 + 0.5, sample depth texture,
    # return homogenous depth z
    let sample_depth = (va@ 'sample_depth opts...)

    fn ssao_read_sample_fib (i seed origin rotation)
        "f32 <- (i32 f32 vec3 mat3)"
        # get sample position:
        let r = (H_SCALE * ((f32 i) + (f32hash seed)))
        let s = ((rotation * r * radius * (fibonacci_point i seed)) + origin)

        # get sample depth:
        let depth = (sample_depth s)

        # range check & accumulate:
        let dist = (abs (origin.z - depth))
        let range_check = (clamp (2.0 - dist / radius) 0.0 1.0)
        (step depth s.z) * range_check

    # pass origin and normal in view space coordinates
    # seed is usually the frame time
    fn ssao_occlusion (origin normal seed)
        "f32 <- (vec3 vec3 f32)"

        let k = (f32hashuv (origin + seed))

        let rangle = (k * 2.0 * pi)
        let rvec = (vec3 (cos rangle) (sin rangle) 0)
        let tangent = (normalize (rvec - normal * (dot rvec normal)))
        let bitangent = (cross normal tangent)
        let rotation = (mat3 tangent bitangent normal)

        let loop (i occlusion) = (unconst 0) (unconst 0.0)
        if (i < SAMPLE_KERNEL_COUNT)
            loop (i + 1)
                occlusion +
                    ssao_read_sample_fib i k origin rotation

        # (exp2 (occ * -4.0)) is a good curve tweak for occlusion btw
        # here we just pass the verbatim one
        occlusion * H_SCALE

    ssao_occlusion

do
    let SSAO
    locals;