simpleraycaster.frag 6.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-2013, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
10
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13
14
15
16
// 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
17
// 
18
19
20
21
// 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.
22
23
24
// 
// ================================================================================================

25
26
27
layout(location = 0) out vec4 out_Color;     ///< outgoing fragment color
layout(location = 1) out vec4 out_FHP;       ///< outgoing fragment first hitpoint
layout(location = 2) out vec4 out_FHN;       ///< outgoing fragment first hit normal
28

29
#include "tools/gradient.frag"
schultezub's avatar
schultezub committed
30
#include "tools/raycasting.frag"
31
#include "tools/shading.frag"
schultezub's avatar
schultezub committed
32
33
34
35
36
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"

uniform vec2 _viewportSizeRCP;
37
uniform float _jitterStepSizeMultiplier;
schultezub's avatar
schultezub committed
38
39


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// ray entry points
uniform sampler2D _entryPoints;
uniform sampler2D _entryPointsDepth;
uniform TextureParameters2D _entryParams;

// ray exit points
uniform sampler2D _exitPoints;
uniform sampler2D _exitPointsDepth;
uniform TextureParameters2D _exitParams;

// DRR volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;

// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;

schultezub's avatar
schultezub committed
58

59
60
61
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;

schultezub's avatar
schultezub committed
62
63
uniform float _samplingStepSize;

64
65
66
67
#ifdef ENABLE_SHADOWING
uniform float _shadowIntensity;
#endif

schultezub's avatar
schultezub committed
68
69
70
71
// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;

/**
schultezub's avatar
schultezub committed
72
 * Performs the raycasting and returns the final fragment color.
schultezub's avatar
schultezub committed
73
74
75
 */
vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) {
    vec4 result = vec4(0.0);
76
    float firstHitT = -1.0;
schultezub's avatar
schultezub committed
77
78
79
80
81
82
83

    // calculate ray parameters
    vec3 direction = exitPoint.rgb - entryPoint.rgb;
    float t = 0.0;
    float tend = length(direction);
    direction = normalize(direction);

84
    jitterEntryPoint(entryPoint, direction, _samplingStepSize * _jitterStepSizeMultiplier);
schultezub's avatar
schultezub committed
85
86

    while (t < tend) {
87
        // compute sample position
schultezub's avatar
schultezub committed
88
        vec3 samplePosition = entryPoint.rgb + t * direction;
89
90

        // lookup intensity and TF
91
        float intensity = texture(_volume, samplePosition).r;
92
        vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
schultezub's avatar
schultezub committed
93

94
95
96
97
#ifdef ENABLE_SHADOWING
        // simple and expensive implementation of hard shadows
        if (color.a > 0.1) {
            // compute direction from sample to light
98
            vec3 L = normalize(_lightSource._position - textureToWorld(_volumeTextureParams, samplePosition).xyz) * _samplingStepSize;
99
100
101
102
103
104
105
106

            bool finished = false;
            vec3 position = samplePosition + L;
            float shadowFactor = 0.0;

            // traverse ray from sample to light
            while (! finished) {
                // grab intensity and TF opacity
107
                intensity = texture(_volume, position).r;
108
                shadowFactor += lookupTF(_transferFunction, _transferFunctionParams, intensity).a;
109
110
111
112
113
114
115

                position += L;
                finished = (shadowFactor > 0.95)
                         || any(lessThan(position, vec3(0.0, 0.0, 0.0)))
                         || any(greaterThan(position, vec3(1.0, 1.0, 1.0)));
            }
            // apply shadow to color
116
            color.rgb *= (1.0 - shadowFactor * _shadowIntensity);
117
118
119
        }
#endif

schultezub's avatar
schultezub committed
120
121
        // perform compositing
        if (color.a > 0.0) {
122
123
#ifdef ENABLE_SHADING
            // compute gradient (needed for shading and normals)
124
125
            vec3 gradient = computeGradient(_volume, _volumeTextureParams, samplePosition);
            color.rgb = calculatePhongShading(textureToWorld(_volumeTextureParams, samplePosition).xyz, _lightSource, _cameraPosition, gradient, color.rgb, color.rgb, vec3(1.0, 1.0, 1.0));
126
#endif
127

128
            // accomodate for variable sampling rates
schultezub's avatar
schultezub committed
129
            color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
130
            result.rgb = result.rgb + color.rgb * color.a  * (1.0 - result.a);
schultezub's avatar
schultezub committed
131
132
133
134
            result.a = result.a + (1.0 -result.a) * color.a;
        }

        // save first hit ray parameter for depth value calculation
135
        if (firstHitT < 0.0 && result.a > 0.0) {
136
            firstHitT = t;
137
            out_FHP = vec4(samplePosition, 1.0);
138
            out_FHN = vec4(normalize(computeGradient(_volume, _volumeTextureParams, samplePosition)), 1.0);
139
        }
schultezub's avatar
schultezub committed
140
141

        // early ray termination
schultezub's avatar
schultezub committed
142
        if (result.a > 0.975) {
schultezub's avatar
schultezub committed
143
144
145
146
            result.a = 1.0;
            t = tend;
        }

147
        // advance to the next evaluation point along the ray
schultezub's avatar
schultezub committed
148
149
150
151
152
        t += _samplingStepSize;
    }

    // calculate depth value from ray parameter
    gl_FragDepth = 1.0;
153
    if (firstHitT >= 0.0) {
154
155
        float depthEntry = texture(_entryPointsDepth, texCoords).z;
        float depthExit = texture(_exitPointsDepth, texCoords).z;
156
157
        gl_FragDepth = calculateDepthValue(firstHitT/tend, depthEntry, depthExit);
    }
schultezub's avatar
schultezub committed
158
159
160
161
162
163
164
165
    return result;
}

/***
 * The main method.
 ***/
void main() {
    vec2 p = gl_FragCoord.xy * _viewportSizeRCP;
166
167
    vec3 frontPos = texture(_entryPoints, p).rgb;
    vec3 backPos = texture(_exitPoints, p).rgb;
schultezub's avatar
schultezub committed
168
169
170
171
172
173
174

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