2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

voxelhierarchy.frag 4.89 KB
Newer Older
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// =============-===================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
// 
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
// 
// ================================================================================================

// XOR Bitmask texture
uniform usampler2D _xorBitmask;

// BBV Lookup volume
uniform usampler2D _voxelHierarchy;
uniform int _vhMaxMipMapLevel;

const int MAXSTEPS = 20;
float OFFSET = 0.001;

// a minimal version of the method above
// (we assume: ray always hits the box)
float IntersectBoxOnlyTFar(in vec3 origin, in vec3 dir, in vec3 box_min, in vec3 box_max)
{
    vec3 tmin = (box_min - origin) / dir; 
    vec3 tmax = (box_max - origin) / dir; 

    vec3 real_max = max(tmin,tmax);

    // the minimal maximum is tFar
    // clamp to 1.0
    return min(1.0, min( min(real_max.x, real_max.y), real_max.z));
}

bool intersectBits(in uvec4 bitRay, in ivec2 texel, in int level, out uvec4 intersectionBitmask)
{
    // Fetch bitmask from hierarchy and compute intersection via bitwise AND
    intersectionBitmask = (bitRay & texelFetch(_voxelHierarchy, texel, level));
    return (intersectionBitmask != uvec4(0));
}

bool intersectHierarchy(in vec3 origin, in vec3 direction, in int level, in vec3 posTNear, out float tFar, out uvec4 intersectionBitmask) {
    // Calculate pixel coordinates ([0,width]x[0,height])
    // of the current position along the ray
    float res = float(1 << (_vhMaxMipMapLevel - level));
    ivec2 pixelCoord = ivec2(posTNear.xy * res);

    // Voxel width and height in the unit cube
    vec2 voxelWH = vec2(1.0) / res;

    // Compute voxel stack (AABB) in the unit cube
    // belonging to this pixel position
    vec2 box_min = pixelCoord * voxelWH; // (left, bottom)

    // Compute intersection with the bounding box
    // It is always assumed that an intersection occurs and
    // that the position of posTNear remains the same
    tFar = IntersectBoxOnlyTFar(origin, direction,
        vec3(box_min, 0.0),
        vec3(box_min + voxelWH, 1.0));

    // Now test if some of the bits intersect
    float zFar = (tFar * direction.z) + origin.z ;

    // Fetch bitmask for ray and intersect with current pixel
    return intersectBits(
        texture(_xorBitmask, vec2(min(posTNear.z, zFar), max(posTNear.z, zFar))),
        pixelCoord, 
        level, 
        intersectionBitmask);
}

float clipFirstHitpoint(in vec3 origin, in vec3 direction, in float tNear, in float tFar) {
    // Compute the exit position of the ray with the scene’s BB
    // tFar = rayBoxIntersection(origin, direction, vec3(0.0), vec3(1.0), tNear);
    // if (tFar > originalTFar) {
    //     vec3 foo = origin + tFar * direction;
    //     out_FHN = vec4(foo, 1.0);
    //     tFar = originalTFar;
    // }

    // Set current position along the ray to the ray’s origin
    vec3 posTNear = origin;
    bool intersectionFound = false;
    uvec4 intersectionBitmask = uvec4(0);

    // It’s faster to not start at the coarsest level
    int level = _vhMaxMipMapLevel / 2;
    for (int i = 0; (i < MAXSTEPS) && (tNear < tFar) && (!intersectionFound); i++) {
        float newTFar = 1.0;
        if (intersectHierarchy(origin, direction, level, posTNear, newTFar, intersectionBitmask)) {
            // If we are at mipmap level 0 and an intersection occurred,
            // we have found an intersection of the ray with the volume
            intersectionFound = (level == 0);

            // Otherwise we have to move down one level and
            // start testing from there
            --level;
        }
        else {
            // If no intersection occurs, we have to advance the
            // position on the ray to test the next element of the hierachy.
            // Furthermore, add a small offset computed beforehand to
            // handle floating point inaccuracy.
            tNear = newTFar + OFFSET;
            posTNear = origin + tNear * direction;

            // Move one level up
            ++level;
        }
    }

    return tNear;
}