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

drrraycaster.frag 5.44 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
5
// 
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
8
9
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
// 
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// 
// ================================================================================================

30
31
32
33
#version 330

out vec4 out_Color;         ///< outgoing fragment color

schultezub's avatar
schultezub committed
34
#include "tools/raycasting.frag"
schultezub's avatar
schultezub committed
35
36
37
38
39
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"

uniform vec2 _viewportSizeRCP;
schultezub's avatar
schultezub committed
40
uniform bool _jitterEntryPoints;
41
uniform float _jitterStepSizeMultiplier;
schultezub's avatar
schultezub committed
42
43
44
45
46

uniform Texture2D _entryPoints;          // ray entry points
uniform Texture2D _exitPoints;           // ray exit points
uniform Texture3D _volume;            // texture lookup parameters for volume_

schultezub's avatar
schultezub committed
47
uniform TransferFunction1D _transferFunction;
schultezub's avatar
schultezub committed
48
49
50
51
52
53
54
55

uniform float _samplingStepSize;
uniform float _shift;
uniform float _scale;

// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;

schultezub's avatar
schultezub committed
56
57
58
59
/**
 * Computes the DRR by simple raycasting and returns the final fragment color.
 */
vec4 raycastDRR(in vec3 entryPoint, in vec3 exitPoint) {
schultezub's avatar
schultezub committed
60
61
62
    vec4 result = vec4(0.0);

    // calculate ray parameters
schultezub's avatar
schultezub committed
63
    vec3 direction = exitPoint.rgb - entryPoint.rgb;
schultezub's avatar
schultezub committed
64
    float t = 0.0;
schultezub's avatar
schultezub committed
65
    float tend = length(direction);
schultezub's avatar
schultezub committed
66
67
    direction = normalize(direction);

schultezub's avatar
schultezub committed
68
    if (_jitterEntryPoints)
69
        jitterEntryPoint(entryPoint, direction, _samplingStepSize * _jitterStepSizeMultiplier);
schultezub's avatar
schultezub committed
70

schultezub's avatar
schultezub committed
71
    while (t < tend) {
schultezub's avatar
schultezub committed
72
        // compute sample position
schultezub's avatar
schultezub committed
73
        vec3 samplePosition = entryPoint.rgb + t * direction;
schultezub's avatar
schultezub committed
74
75
76
77

        // lookup intensity and TF
        float intensity = getElement3DNormalized(_volume, samplePosition).a;
        vec4 color = lookupTF(_transferFunction, intensity);
schultezub's avatar
schultezub committed
78
79

#ifdef DEPTH_MAPPING
schultezub's avatar
schultezub committed
80
81
        // use Bernstein Polynomials for depth-color mapping
        float depth = t / tend;
schultezub's avatar
schultezub committed
82
            
schultezub's avatar
schultezub committed
83
84
85
        float b02 = (1-depth) * (1-depth);
        float b12 = 2 * depth * (1-depth);
        float b22 = depth * depth;
schultezub's avatar
schultezub committed
86
            
schultezub's avatar
schultezub committed
87
        color = vec4(0.75*b02 + 0.25*b12, b12, 0.25*b12 + 0.75*b22, 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP));
schultezub's avatar
schultezub committed
88
/*            float t_sq = depth * depth;
schultezub's avatar
schultezub committed
89
90
91
92
93
94
95
96
        float inv_t_sq = (1-depth) * (1-depth);
        float b04 = inv_t_sq * inv_t_sq;
        float b24 = 6 * t_sq * inv_t_sq;
        float b44 = t_sq * t_sq;
        color = vec4(0.5*b04 + 0.5*b24, b24, 0.5*b24 + 0.5*b44, 1.0 - pow(1.0 - color.a, samplingStepSize_ * SAMPLING_BASE_INTERVAL_RCP));*/

        result.rgb = result.rgb + (1.0 - result.a) * color.a * color.rgb;
        result.a = result.a + color.a * _scale;
schultezub's avatar
schultezub committed
97
#else
schultezub's avatar
schultezub committed
98
99
100
        // perform compositing (account for differen step size / sampling rate)
        color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
        result.a = result.a + color.a * _scale;
schultezub's avatar
schultezub committed
101
102
#endif       

schultezub's avatar
schultezub committed
103
        t += _samplingStepSize;
schultezub's avatar
schultezub committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    }

#ifdef DEPTH_MAPPING
    result.rgb = result.rgb * vec3(exp(-result.a + _shift));
    //result.rgb = exp(-result.rgb * result.a + shift_);
#else
#ifdef DRR_INVERT
    // apply e-function, as we want the "negative" X-Ray image, we invert the intensity result
    result.rgb = 1 - vec3(exp(-result.a + _shift));
#else
    // apply e-function, the normal way
    result.rgb = vec3(exp(-result.a + _shift));
#endif
#endif
    result.a = 1.0;
    return result;
}

/***
 * The main method.
 ***/
void main() {
    vec2 p = gl_FragCoord.xy * _viewportSizeRCP;
schultezub's avatar
schultezub committed
127
128
    vec3 frontPos = getElement2DNormalized(_entryPoints, p).rgb;
    vec3 backPos = getElement2DNormalized(_exitPoints, p).rgb;
schultezub's avatar
schultezub committed
129
130
131
132
133
134
135

    //determine whether the ray has to be casted
    if (frontPos == backPos) {
        //background need no raycasting
        discard;
    } else {
        //fragCoords are lying inside the boundingbox
136
        out_Color = raycastDRR(frontPos, backPos);
schultezub's avatar
schultezub committed
137
138
    }
}