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

visualizationprocessor.cpp 8.12 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-2015, 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
// 
// ================================================================================================

schultezub's avatar
schultezub committed
25 26
#include "visualizationprocessor.h"

27
#include "cgt/textureunit.h"
28
#include "core/datastructures/imagedata.h"
Jakob Weiss's avatar
Jakob Weiss committed
29 30
#include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h"
31

schultezub's avatar
schultezub committed
32
namespace campvis {
schultezub's avatar
schultezub committed
33

34 35 36 37
    const std::string VisualizationProcessor::loggerCat_ = "CAMPVis.core.datastructures.VisualizationProcessor";

// ================================================================================================

38
    VisualizationProcessor::VisualizationProcessor(IVec2Property* viewportSizeProp)
schultezub's avatar
schultezub committed
39
        : AbstractProcessor()
40
        , p_lqMode("LqMode", "Low Quality Mode", false)
41
        , _fbo(0)
42
        , _viewportSizeProperty(viewportSizeProp)
schultezub's avatar
schultezub committed
43
    {
44 45 46 47
        if (_viewportSizeProperty) {
            _viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
            setPropertyInvalidationLevel(*_viewportSizeProperty, INVALID_RESULT);
        }
schultezub's avatar
schultezub committed
48 49 50 51 52
    }

    VisualizationProcessor::~VisualizationProcessor() {
    }

53 54
    void VisualizationProcessor::init() {
        AbstractProcessor::init();
55

56
        cgtAssert(_viewportSizeProperty != 0, "The pointer to the viewport size property must not be 0!");
57
        addProperty(p_lqMode);
58

59
        _fbo = new cgt::FramebufferObject();
60 61 62
    }

    void VisualizationProcessor::deinit() {
63 64 65 66 67
        if (_viewportSizeProperty) {
            _viewportSizeProperty->s_changed.disconnect(this);
            _viewportSizeProperty = nullptr;
        }

68 69 70 71
        delete _fbo;
        AbstractProcessor::deinit();
    }

Jakob Weiss's avatar
Jakob Weiss committed
72
    void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, GLenum attachment, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
73
        cgtAssert(_fbo->isActive(), "Trying to attach a texture while FBO is not bound!");
74

75
        // acquire a new TextureUnit, so that we don't mess with other currently bound textures during texture upload...
76
        cgt::TextureUnit rtUnit;
77 78 79 80 81
        rtUnit.activate();

        // Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

82
        // Check the render data if we can reuse a texture
Jakob Weiss's avatar
Jakob Weiss committed
83
        cgt::Texture* tex = nullptr;
84
        if (renderData) {
85
            // check if we can get a GL representation of the desired texture
Jakob Weiss's avatar
Jakob Weiss committed
86
            ImageRepresentationGL* glRep = nullptr;
Jakob Weiss's avatar
Jakob Weiss committed
87
            if (attachment == GL_DEPTH_ATTACHMENT) {
Jakob Weiss's avatar
Jakob Weiss committed
88 89
                if(auto id = (*renderData)->getDepthTexture())
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
Jakob Weiss's avatar
Jakob Weiss committed
90 91
            }
            else {
92
                if(auto id =(*renderData)->getColorTexture(_fbo->getNumColorAttachments())) //_fbo->getNumColorAttachments() is the index of the texture that is to be created
Jakob Weiss's avatar
Jakob Weiss committed
93
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
Jakob Weiss's avatar
Jakob Weiss committed
94 95
            }
            
96
            // check if the texture is compatible with what we want, and in that case detach from the old RenderTargetData
Jakob Weiss's avatar
Jakob Weiss committed
97 98 99 100 101 102 103
            if (glRep) {
                tex = const_cast<cgt::Texture*>(glRep->getTexture());
                if (tex->getType() != GL_TEXTURE_2D || tex->getDimensions() != getRenderTargetSize()
                    || tex->getInternalFormat() != internalFormat)
                    tex = nullptr;
                else {
                    // somehow detach the cgt::Texture from the ImageRepresentationGL
104 105
                    // yes this is horrible - however, we know that renderData has write access, ergo
                    // we can safely do this const_cast
Jakob Weiss's avatar
Jakob Weiss committed
106 107 108 109 110 111
                    const_cast<ImageData*>(glRep->getParent())->removeRepresentationUnsafe<ImageRepresentationGL>();
                }

            }
        }

112
        // if we could not get the texture from a previous render target, create a new one
Jakob Weiss's avatar
Jakob Weiss committed
113 114 115 116
        if (!tex) {
            // create texture
            tex = new cgt::Texture(GL_TEXTURE_2D, getRenderTargetSize(), internalFormat, cgt::Texture::LINEAR);
        }
117
        tex->setWrapping(cgt::Texture::CLAMP_TO_EDGE);
118 119 120 121 122

        // attach texture to FBO
        _fbo->attachTexture(tex, attachment);
    }

Jakob Weiss's avatar
Jakob Weiss committed
123
    void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
124 125
        GLenum attachment = 0;
        switch(internalFormat) {
126
            case GL_R32F:
127 128 129 130 131 132 133 134
            case GL_RGB:
            case GL_RGB16F_ARB:
            case GL_RGBA:
            case GL_RGBA8:
            case GL_RGBA16:
            case GL_RGBA16F:
            case GL_RGBA32F:
                if (_fbo->getNumColorAttachments() >= static_cast<size_t>(GpuCaps.getMaxColorAttachments())) {
135
                    cgtAssert(false, "Tried to attach more color textures to FBO than supported!");
136 137 138 139 140 141 142 143 144 145 146
                    LWARNING("Tried to attach more color textures to FBO than supported, aborted.");
                    return;
                }
                attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + _fbo->getNumColorAttachments());
                break;

            case GL_DEPTH_COMPONENT16:
            case GL_DEPTH_COMPONENT24:
#ifdef GL_DEPTH_COMPONENT32F
            case GL_DEPTH_COMPONENT32F:
#endif
147
                cgtAssert(_fbo->getDepthAttachment() == 0, "Tried to attach more than one depth texture.");
148 149 150 151
                attachment = GL_DEPTH_ATTACHMENT;
                break;

            default:
152
                cgtAssert(false, "Unknown internal format!");
153 154 155 156
        }
        createAndAttachTexture(internalFormat, attachment);
    }

157
    cgt::ivec2 VisualizationProcessor::getEffectiveViewportSize() const {
158 159 160
        return (p_lqMode.getValue() ? _viewportSizeProperty->getValue() / 2 : _viewportSizeProperty->getValue());
    }

161 162
    cgt::ivec3 VisualizationProcessor::getRenderTargetSize() const {
        return cgt::ivec3(getEffectiveViewportSize(), 1);
163 164
    }

Jakob Weiss's avatar
Jakob Weiss committed
165 166
    void VisualizationProcessor::createAndAttachColorTexture(ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
        createAndAttachTexture(GL_RGBA8, renderData);
167 168
    }

Jakob Weiss's avatar
Jakob Weiss committed
169 170
    void VisualizationProcessor::createAndAttachDepthTexture(ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
        createAndAttachTexture(GL_DEPTH_COMPONENT24, renderData);
171 172
    }

173
    void VisualizationProcessor::setViewportSizeProperty(IVec2Property* viewportSizeProp) {
174
        cgtAssert(viewportSizeProp != nullptr, "Pointer must not be nullptr.");
175

176
        if (_viewportSizeProperty != nullptr) {
177
            _viewportSizeProperty->s_changed.disconnect(this);
178 179
        }

180 181
        _viewportSizeProperty = viewportSizeProp;
        _viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
182
        setPropertyInvalidationLevel(*viewportSizeProp, INVALID_RESULT);
183
        invalidate(INVALID_RESULT);
184 185
    }

schultezub's avatar
schultezub committed
186
}