rev: 21c5e6d2f665d0e8b4ff917a51b664c895dab2ed tukan/tukan/projection.sc -rw-r--r-- 2.5 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
using import glm

struct ProjectionSetup
    aspect : vec2
    z_coeffs : vec2
    w_coeffs : vec2
    zw_inv : vec2

    method 'repr (self)
        .. "<aspect=" (repr self.aspect)
            \ " z_coeffs=" (repr self.z_coeffs)
            \ " w_coeffs=" (repr self.w_coeffs)
            \ " zw_inv=" (repr self.zw_inv)
            ">"

    # (ProjectionSetup vec2 vec2 vec2)
    method 'apply-type (cls aspect z_coeffs w_coeffs)
        let det =
            -
                z_coeffs.x * w_coeffs.y
                z_coeffs.y * w_coeffs.x
        'structof cls
            aspect = aspect
            z_coeffs = z_coeffs
            w_coeffs = w_coeffs
            zw_inv =
                vec2
                    (- w_coeffs.x) / det
                    z_coeffs.x / det

    # infinite far plane perspective transform
        for this to work, the depth buffer must be reversed;
        glDepthFunc must be set to GL_GREATER, glClearDepth set to 0,
        and glDepthRangedNV set to -1, 1;
    # ('ifp-perspective ProjectionSetup vec2 f32)
    method 'ifp-perspective (cls aspect near)
        ProjectionSetup
            aspect = aspect
            z_coeffs =
                vec2 0 near
            w_coeffs =
                vec2 1 0

    # linear orthographic with near = 1 far = 0
        for this to work, the depth buffer must be reversed;
        glDepthFunc must be set to GL_GREATER, glClearDepth set to 0,
        and glDepthRangedNV set to -1, 1;
    # ('orthographic ProjectionSetup vec2 f32 f32)
    method 'orthographic (cls aspect near far)
        ProjectionSetup
            aspect = aspect
            z_coeffs =
                /
                    vec2 1
                        - far
                    near - far
            w_coeffs =
                vec2 0 1

    # generic projection transform; allows for orthographic
    # and perspective coeffs
    # ('project self vec4)
    method 'project (self v)
        vec4
            v.xy * self.aspect
            dot v.zw self.z_coeffs
            dot v.zw self.w_coeffs

    # ('project-inverse self vec4)
    method 'project-inverse (self v)
        let z =
            /
                v.z * self.w_coeffs.y - self.z_coeffs.y
                self.z_coeffs.x - v.z * self.w_coeffs.x
        let w =
            z * self.w_coeffs.x + self.w_coeffs.y
        vec4 (v.xy * w / self.aspect) z 1

if main-module?
    print
        'project
            'orthographic ProjectionSetup (vec2 1) 0 1
            vec4 0.1 0.2 0.3 1.0

locals;