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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 
// ================================================================================================

#include "glreduction.h"

#include "tgt/logmanager.h"
#include "tgt/framebufferobject.h"
#include "tgt/shadermanager.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"

#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
        tgtAssert(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
97
98
    std::vector<float> GlReduction::reduce(const tgt::Texture* texture) {
        std::vector<float> toReturn;

99
        tgtAssert(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
        const tgt::ivec3& size = texture->getDimensions();
110
        tgt::ivec2 texSize = size.xy();
111
112
113
114
115
116

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

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

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

        const tgt::Texture* inputTex = texture;
        tgt::Texture* outputTex = tempTextures[1];
129
130
131
132
133
134

        // create and initialize FBO
        _fbo = new tgt::FramebufferObject();
        _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
236
237
238
            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:
                tgtAssert(false, "Should not reach this, wrong enum value?");
                return "";
                break;
239
240
241
        }
    }

242
}