The name of the initial branch for new projects is now "main" instead of "master". Existing projects remain unchanged. More information: https://doku.lrz.de/display/PUBLIC/GitLab

raycastingprocessor.cpp 8.89 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 55
        , _shader(0)
        , _bindEntryExitDepthTextures(bindEntryExitDepthTextures)
    {
56 57 58 59 60 61 62 63
        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);
64 65 66 67 68 69 70 71
    }

    RaycastingProcessor::~RaycastingProcessor() {

    }

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

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

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

        delete _minReduction;
        delete _maxReduction;

85 86 87
        VisualizationProcessor::deinit();
    }

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

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

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

134
                // compute and set camera parameters
135
                const cgt::Camera& cam = camera->getCamera();
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
                cgt::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
                }
                else {
156
                    cgt::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
                _shader->deactivate();
164
                cgt::TextureUnit::setZeroUnit();
165 166 167 168 169 170 171
                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
}