glreduction.cpp 8.84 KB
Newer Older
1
2
3
4
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
6
7
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
11
12
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
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 "glreduction.h"

27
28
29
30
31
#include "cgt/logmanager.h"
#include "cgt/framebufferobject.h"
#include "cgt/shadermanager.h"
#include "cgt/texture.h"
#include "cgt/textureunit.h"
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#include "core/datastructures/facegeometry.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/tools/quadrenderer.h"

#include <algorithm>

#define DIV_CEIL(x,y) ((x) > 0) ? (1 + ((x) - 1)/(y)) : ((x) / (y))

namespace campvis {

    const std::string GlReduction::loggerCat_ = "CAMPVis.modules.registration.GlReduction";

Hossain Mahmud's avatar
Hossain Mahmud committed
46
    GlReduction::GlReduction(ReductionOperator reductionOperator)
47
        : _reductionOperator(reductionOperator)
48
        , _shader1d(0)
49
50
        , _shader2d(0)
        , _shader3d(0)
51
52
        , _fbo(0)
    {
Hossain Mahmud's avatar
Hossain Mahmud committed
53
54
55
56
        _shader1d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_1D\n");
        _shader2d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_2D\n");
        _shader3d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_3D\n");

57
        if (_shader1d == 0 || _shader2d == 0 || _shader3d == 0) {
58
59
60
61
            LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
            return;
        }

62
63
        _shader1d->setAttributeLocation(0, "in_Position");
        _shader1d->setAttributeLocation(1, "in_TexCoord");
64
65
66
67
        _shader2d->setAttributeLocation(0, "in_Position");
        _shader2d->setAttributeLocation(1, "in_TexCoord");
        _shader3d->setAttributeLocation(0, "in_Position");
        _shader3d->setAttributeLocation(1, "in_TexCoord");
68
69
70
    }

    GlReduction::~GlReduction() {
71
        ShdrMgr.dispose(_shader1d);
72
73
        ShdrMgr.dispose(_shader2d);
        ShdrMgr.dispose(_shader3d);
74
75
    }

76
    std::vector<float> GlReduction::reduce(const ImageData* image) {
77
        cgtAssert(image != 0, "Image must not be 0!");
78
        if (_shader1d == 0 || _shader2d == 0 || _shader3d == 0) {
79
            LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
80
            return std::vector<float>();
81
82
83
        }
        if (image == 0) {
            LERROR("Empty image received - nothing to reduce!");
84
            return std::vector<float>();
85
86
87
88
89
        }

        const ImageRepresentationGL* repGl = image->getRepresentation<ImageRepresentationGL>();
        if (repGl == 0) {
            LERROR("Could not convert input image to OpenGL texture - no reduction possible!");
90
            return std::vector<float>();
91
92
        }

93
94
95
        return reduce(repGl->getTexture());
    }
    
96
    std::vector<float> GlReduction::reduce(const cgt::Texture* texture) {
97
98
        std::vector<float> toReturn;

99
        cgtAssert(texture != 0, "Image must not be 0!");
100
        if (_shader1d == 0 || _shader2d == 0 || _shader3d == 0) {
101
            LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
102
            return toReturn;
103
104
105
        }
        if (texture == 0) {
            LERROR("Empty texture received - nothing to reduce!");
106
            return toReturn;
107
        }
108

109
110
        const cgt::ivec3& size = texture->getDimensions();
        cgt::ivec2 texSize = size.xy();
111
112
113
114
115

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

        // get a free texture unit
116
        cgt::TextureUnit inputUnit;
117
        inputUnit.activate();
118
119

        // create temporary textures
120
        cgt::Texture* tempTextures[2];
121
        for (size_t i = 0; i < 2; ++i) {
122
            tempTextures[i] = new cgt::Texture(0, cgt::ivec3(texSize, 1), GL_RGBA, GL_RGBA32F, GL_FLOAT, cgt::Texture::NEAREST);
123
            tempTextures[i]->uploadTexture();
124
            tempTextures[i]->setWrapping(cgt::Texture::CLAMP_TO_EDGE);
125
        }
126

127
128
        const cgt::Texture* inputTex = texture;
        cgt::Texture* outputTex = tempTextures[1];
129
130

        // create and initialize FBO
131
        _fbo = new cgt::FramebufferObject();
132
133
134
        _fbo->activate();
        LGL_ERROR;

135
136
137
138
        // perform 3D reduction if needed
        if (texture->getDimensions().z > 1) {
            _shader3d->activate();
            _fbo->attachTexture(outputTex);
139

140
141
142
143
144
145
146
            inputTex->bind();
            _shader3d->setUniform("_texture", inputUnit.getUnitNumber());
            _shader3d->setUniform("_textureSize", size);

            glViewport(0, 0, texSize.x, texSize.y);
            QuadRdr.renderQuad();
            _shader3d->deactivate();
147

148
149
150
151
            inputTex = outputTex;
            outputTex = tempTextures[0];
            LGL_ERROR;
        }
152

153
154
155
156
        // perform 2D reduction if needed
        if (texture->getDimensions().y > 1) {
            _shader2d->activate();
            _fbo->attachTexture(outputTex);
157

158
159
160
161
162
            inputTex->bind();
            _shader2d->setUniform("_texture", inputUnit.getUnitNumber());
            _shader2d->setUniform("_textureSize", size.xy());

            glViewport(0, 0, texSize.x, 1);
163
            QuadRdr.renderQuad();
164
            _shader2d->deactivate();
165

166
167
168
            inputTex = outputTex;
            outputTex = (outputTex == tempTextures[1]) ? tempTextures[0] : tempTextures[1];
            LGL_ERROR;
169
170
        }

171
172
173
174
175
176
177
178
        // finally, perform 1D reduction if needed
        {
            _shader1d->activate();
            _fbo->attachTexture(outputTex);

            inputTex->bind();
            _shader1d->setUniform("_texture", inputUnit.getUnitNumber());
            _shader1d->setUniform("_textureSize", size.xy());
179

180
181
182
183
184
            glViewport(0, 0, 1, 1);
            QuadRdr.renderQuad();
            _shader1d->deactivate();
            LGL_ERROR;
        }
185
186

        // read back stuff
187
188
189
        GLenum readBackFormat = outputTex->getFormat();
        size_t channels = outputTex->getNumChannels();
        toReturn.resize(channels);
190
        glReadBuffer(GL_COLOR_ATTACHMENT0);
191
        glReadPixels(0, 0, 1, 1, readBackFormat, GL_FLOAT, &toReturn.front());
192
193
194
195
196
197
198
199
        LGL_ERROR;

        // clean up...
        _fbo->detachAll();
        _fbo->deactivate();
        delete _fbo;
        _fbo = 0;

200
201
        delete tempTextures[0];
        delete tempTextures[1];
202
203
        LGL_ERROR;

204
        return toReturn;
205
206
207
    }


208
209
    std::string GlReduction::generateGlslHeader(ReductionOperator reductionOperator) {
        switch (reductionOperator) {
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
            case MIN:
                return 
                    "#define REDUCTION_OP_2(a, b) min(a, b)\n"
                    "#define REDUCTION_OP_4(a, b, c, d) min(a, min(b, min(c, d)))\n";
                break;
            case MAX:
                return 
                    "#define REDUCTION_OP_2(a, b) max(a, b)\n"
                    "#define REDUCTION_OP_4(a, b, c, d) max(a, max(b, max(c, d)))\n";
                break;
            case PLUS:
                return 
                    "#define REDUCTION_OP_2(a, b) a+b\n"
                    "#define REDUCTION_OP_4(a, b, c, d) a+b+c+d\n";
                break;
            case MULTIPLICATION:
                return 
                    "#define REDUCTION_OP_2(a, b) a*b\n"
                    "#define REDUCTION_OP_4(a, b, c, d) a*b*c*d\n";
                break;
            case MIN_MAX_DEPTH_ONLY:
                return 
                    "#define REDUCTION_OP_2(a, b) vec4(min(a.r, b.r), max(a.g, b.g), 0.0, 0.0)\n"
                    "#define REDUCTION_OP_4(a, b, c, d) vec4(min(a.r, min(b.r, min(c.r, d.r))), max(a.g, max(b.g, max(c.g, d.g))), 0.0, 0.0)\n";
                break;
            default:
236
                cgtAssert(false, "Should not reach this, wrong enum value?");
237
238
                return "";
                break;
239
240
241
        }
    }

242
}