visualizationprocessor.cpp 8.07 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 85
        if (renderData) {`
            // check if we can get a GL representation of the desired texture
Jakob Weiss's avatar
Jakob Weiss committed
86 87 88 89 90
            ImageRepresentationGL* glRep;
            if (attachment == GL_DEPTH_ATTACHMENT)
                if(auto id = (*renderData)->getDepthTexture())
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
            else 
91
                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
92 93
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));

94
            // 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
95 96 97 98 99 100 101
            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
102 103
                    // 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
104 105 106 107 108 109
                    const_cast<ImageData*>(glRep->getParent())->removeRepresentationUnsafe<ImageRepresentationGL>();
                }

            }
        }

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

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

Jakob Weiss's avatar
Jakob Weiss committed
121
    void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
122 123
        GLenum attachment = 0;
        switch(internalFormat) {
124
            case GL_R32F:
125 126 127 128 129 130 131 132
            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())) {
133
                    cgtAssert(false, "Tried to attach more color textures to FBO than supported!");
134 135 136 137 138 139 140 141 142 143 144
                    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
145
                cgtAssert(_fbo->getDepthAttachment() == 0, "Tried to attach more than one depth texture.");
146 147 148 149
                attachment = GL_DEPTH_ATTACHMENT;
                break;

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

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

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

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

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

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

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

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

schultezub's avatar
schultezub committed
184
}