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

raycastingprocessor.cpp 8.82 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-2014, 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
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
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
#include "raycastingprocessor.h"

27
28
29
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
30
31

#include "core/datastructures/imagedata.h"
32
#include "core/datastructures/renderdata.h"
33
#include "core/tools/glreduction.h"
34
35
36

#include "core/classification/simpletransferfunction.h"

schultezub's avatar
schultezub committed
37
38
namespace campvis {
    const std::string RaycastingProcessor::loggerCat_ = "CAMPVis.modules.vis.RaycastingProcessor";
39

40
    RaycastingProcessor::RaycastingProcessor(IVec2Property* viewportSizeProp, const std::string& fragmentShaderFileName, bool bindEntryExitDepthTextures, const std::string& customGlslVersion /*= ""*/)
41
        : VisualizationProcessor(viewportSizeProp)
42
        , p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
43
44
        , p_entryImageID("entryImageID", "Input Entry Points Image", "", DataNameProperty::READ)
        , p_exitImageID("exitImageID", "Input Exit Points Image", "", DataNameProperty::READ)
45
        , p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
46
        , p_camera("camera", "Camera")
47
        , p_transferFunction("TransferFunction", "Transfer Function", new SimpleTransferFunction(256))
48
        , p_jitterStepSizeMultiplier("jitterStepSizeMultiplier", "Jitter Step Size Multiplier", 1.f, 0.f, 1.f)
49
        , p_samplingRate("SamplingRate", "Sampling Rate", 2.f, 0.1f, 10.f, 0.1f)
50
        , _fragmentShaderFilename(fragmentShaderFileName)
51
        , _customGlslVersion(customGlslVersion)
52
53
54
        , _shader(0)
        , _bindEntryExitDepthTextures(bindEntryExitDepthTextures)
    {
55
56
57
58
59
60
61
62
        addProperty(p_sourceImageID, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES);
        addProperty(p_entryImageID);
        addProperty(p_exitImageID);
        addProperty(p_targetImageID);
        addProperty(p_camera);  
        addProperty(p_transferFunction);
        addProperty(p_jitterStepSizeMultiplier);
        addProperty(p_samplingRate);
63
64
65
66
67
68
69
70
    }

    RaycastingProcessor::~RaycastingProcessor() {

    }

    void RaycastingProcessor::init() {
        VisualizationProcessor::init();
71
        _shader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", _fragmentShaderFilename, generateHeader(), _customGlslVersion);
72
73
        _shader->setAttributeLocation(0, "in_Position");
        _shader->setAttributeLocation(1, "in_TexCoord");
74
75
76

        _minReduction = new GlReduction(GlReduction::MIN);
        _maxReduction = new GlReduction(GlReduction::MAX);
77
78
79
80
81
    }

    void RaycastingProcessor::deinit() {
        ShdrMgr.dispose(_shader);
        _shader = 0;
82
83
84
85

        delete _minReduction;
        delete _maxReduction;

86
87
88
        VisualizationProcessor::deinit();
    }

89
    void RaycastingProcessor::updateResult(DataContainer& data) {
90
        ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
91
92
        ScopedTypedData<RenderData> entryPoints(data, p_entryImageID.getValue());
        ScopedTypedData<RenderData> exitPoints(data, p_exitImageID.getValue());
93
94
95

        if (img != 0 && entryPoints != 0 && exitPoints != 0) {
            if (img->getDimensionality() == 3) {
96
97
98
99
100
101
102
103
104
105
106
                // little hack to support LOD texture lookup for the gradients:
                // if texture does not yet have mipmaps, create them.
                const tgt::Texture* tex = img->getTexture();
                if (tex->getFilter() != tgt::Texture::MIPMAP) {
                    const_cast<tgt::Texture*>(tex)->setFilter(tgt::Texture::MIPMAP);
                    glGenerateMipmap(GL_TEXTURE_3D);
                    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                    LGL_ERROR;
                }

107
                _shader->activate();
108
                _shader->setIgnoreUniformLocationError(true);
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

                // Compute min/max depth if needed by shader
                if (_shader->getUniformLocation("_minDepth") != -1) {
                    _shader->deactivate();
                    float minDepth = _minReduction->reduce(entryPoints->getDepthTexture()).front();
                    _shader->activate();

                    _shader->setUniform("_minDepth", minDepth);
                }
                if (_shader->getUniformLocation("_maxDepth") != -1) {
                    _shader->deactivate();
                    float maxDepth = _maxReduction->reduce(exitPoints->getDepthTexture()).front();
                    _shader->activate();

                    _shader->setUniform("_maxDepth", maxDepth);
                }

126
                decorateRenderProlog(data, _shader);
127
                _shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(getEffectiveViewportSize()));
128
                _shader->setUniform("_jitterStepSizeMultiplier", p_jitterStepSizeMultiplier.getValue());
129

130
                // compute sampling step size relative to volume size
131
132
                float samplingStepSize = 1.f / (p_samplingRate.getValue() * tgt::max(img->getSize()));
                _shader->setUniform("_samplingStepSize", samplingStepSize);
133

134
                // compute and set camera parameters
135
                const tgt::Camera& cam = p_camera.getValue();
136
137
                float n = cam.getNearDist();
                float f = cam.getFarDist();
138
                _shader->setUniform("_cameraPosition", cam.getPosition());
139
140
141
142
143
144
                _shader->setUniform("const_to_z_e_1", 0.5f + 0.5f*((f+n)/(f-n)));
                _shader->setUniform("const_to_z_e_2", ((f-n)/(f*n)));
                _shader->setUniform("const_to_z_w_1", ((f*n)/(f-n)));
                _shader->setUniform("const_to_z_w_2", 0.5f*((f+n)/(f-n))+0.5f);
                _shader->setIgnoreUniformLocationError(false);

145
                // bind input textures
146
                tgt::TextureUnit volumeUnit, entryUnit, exitUnit, tfUnit;
147
                img->bind(_shader, volumeUnit, "_volume", "_volumeTextureParams");
148
                p_transferFunction.getTF()->bind(_shader, tfUnit);
149
150

                if (! _bindEntryExitDepthTextures) {
151
152
                    entryPoints->bindColorTexture(_shader, entryUnit, "_entryPoints", "_entryParams");
                    exitPoints->bindColorTexture(_shader, exitUnit, "_exitPoints", "_exitParams");
153
                    processImpl(data, img);
154
155
156
                }
                else {
                    tgt::TextureUnit entryUnitDepth, exitUnitDepth;
157
158
                    entryPoints->bind(_shader, entryUnit, entryUnitDepth, "_entryPoints", "_entryPointsDepth", "_entryParams");
                    exitPoints->bind(_shader, exitUnit, exitUnitDepth, "_exitPoints", "_exitPointsDepth", "_exitParams");
159
                    processImpl(data, img);
160
161
                }

162
                decorateRenderEpilog(_shader);
163
164
165
166
167
168
169
170
171
                _shader->deactivate();
                tgt::TextureUnit::setZeroUnit();
                LGL_ERROR;
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
172
            LDEBUG("No suitable input image found.");
173
174
175
176
        }
    }

    std::string RaycastingProcessor::generateHeader() const {
177
        std::string toReturn = getDecoratedHeader();
178
179
180
        return toReturn;
    }

181
182
183
184
185
    void RaycastingProcessor::updateProperties(DataContainer& dc) {
        ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
        p_transferFunction.setImageHandle(img.getDataHandle());
    }

186
187
188
189
190
    void RaycastingProcessor::updateShader() {
        _shader->setHeaders(generateHeader());
        _shader->rebuild();
    }

191
}