raycastingprocessor.cpp 8.96 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/cameradata.h"
32
#include "core/datastructures/imagedata.h"
33
#include "core/datastructures/renderdata.h"
34
#include "core/tools/glreduction.h"
35
36
37

#include "core/classification/simpletransferfunction.h"

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

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

    RaycastingProcessor::~RaycastingProcessor() {

    }

    void RaycastingProcessor::init() {
        VisualizationProcessor::init();
74
        _shader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", _fragmentShaderFilename, generateHeader(), _customGlslVersion);
75
76
77

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

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

        delete _minReduction;
        delete _maxReduction;

87
88
89
        VisualizationProcessor::deinit();
    }

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

96
        if (img != nullptr && entryPoints != nullptr && exitPoints != nullptr && camera != nullptr) {
97
            if (img->getDimensionality() == 3) {
98
99
                // little hack to support LOD texture lookup for the gradients:
                // if texture does not yet have mipmaps, create them.
100
101
102
                const cgt::Texture* tex = img->getTexture();
                if (tex->getFilter() != cgt::Texture::MIPMAP) {
                    const_cast<cgt::Texture*>(tex)->setFilter(cgt::Texture::MIPMAP);
103
104
105
106
107
108
                    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;
                }

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

                // 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);
                }

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

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

136
                // compute and set camera parameters
137
                const cgt::Camera& cam = camera->getCamera();
138
139
                float n = cam.getNearDist();
                float f = cam.getFarDist();
140
                _shader->setUniform("_cameraPosition", cam.getPosition());
141
142
143
144
145
146
                _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);

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

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

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

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

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

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

193
}