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

voxelhierarchymapper.cpp 9.09 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
// 
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
// 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
// 
// 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.
// 
// ================================================================================================

#include "voxelhierarchymapper.h"

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

#include "core/classification/abstracttransferfunction.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/geometrydatafactory.h"

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

namespace campvis {

    std::string VoxelHierarchyMapper::loggerCat_ = "CAMPVis.modules.vis.VoxelHierarchyMapper";

    VoxelHierarchyMapper::VoxelHierarchyMapper()
46
47
        : _xorBitmaskShader(nullptr)
        , _hierarchyRendererShader(nullptr)
48
49
        , _mimapRendererShader(nullptr)
        , _fbo(nullptr)
50
        , _xorBitmaskTexture(nullptr)
51
52
53
        , _hierarchyTexture(nullptr)
        , _quad(nullptr)
    {  
54
        _xorBitmaskShader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", "modules/vis/glsl/xorbitmask.frag", "", "400");
55
56
        _hierarchyRendererShader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", "modules/vis/glsl/hierarchyrenderer.frag", "", "400");
        _mimapRendererShader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", "modules/vis/glsl/mipmaprenderer.frag", "", "400");
57
        _fbo = new cgt::FramebufferObject();
58

59
60
61
        _quad = GeometryDataFactory::createQuad(cgt::vec3(-1.f), cgt::vec3(1.f), cgt::vec3(1.f, 1.f, 0.f), cgt::vec3(0.f, 0.f, 0.f));

        createXorBitmaskTexture();
62
63
64
    }

    VoxelHierarchyMapper::~VoxelHierarchyMapper() {
65
        ShdrMgr.dispose(_xorBitmaskShader);
66
67
        ShdrMgr.dispose(_hierarchyRendererShader);
        ShdrMgr.dispose(_mimapRendererShader);
68
69
70

        delete _xorBitmaskTexture;
        delete _hierarchyTexture;
71
72
73
74
        delete _quad;
    }

    void VoxelHierarchyMapper::createHierarchy(const ImageRepresentationGL* image, AbstractTransferFunction* transferFunction) {
75
76
        cgtAssert(image != nullptr, "Image must not be 0.");
        cgtAssert(transferFunction != nullptr, "Transfer function must not be 0.");
77
78
79
80
81
82
83
84
85
        
        // perform ceiling integer division:
        // z is not considered.
        _brickSize = 2;
        _dimBricks = image->getSize();
        for (int i = 0; i < 2; ++i)
            _dimBricks.elem[i] = DIV_CEIL(_dimBricks.elem[i], _brickSize);

        // set the depth of the bricks
86
        _brickDepth = DIV_CEIL(_dimBricks.z, 128);
87
88

        // since the texture is a 2D texture and the elements store the depth  will pack VOXEL_DEPTH number of values along the z axis into one block, the _dimBricks.z is 
89
        _dimBricks.z = 128;
90
91

        _dimPackedBricks = _dimBricks;
92
        _dimPackedBricks.z = 1;
93
94
95

        _maxMipmapLevel = computeMaxLevel(_dimPackedBricks.x, _dimPackedBricks.y);

96
        cgtAssert(_dimPackedBricks.z == 1, "This should not happen!");
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124


        // create initial texture:
        createEmptyTextureWithMipMaps();
        renderInitialHierarchy(image, transferFunction);

        // generate mipmap levels
        renderMipmaps();
    }



    GLuint VoxelHierarchyMapper::computeMaxLevel(size_t resolutionX, size_t resolutionY) {
        GLuint count = 0;
        GLuint resolution = static_cast<GLuint>(std::max(resolutionX, resolutionY));

        while (resolution) {
            resolution /= 2;
            count++;
        }
        return count-1;
    }

    void VoxelHierarchyMapper::renderMipmaps() {
        LDEBUG("Start computing the levels of the voxel object.");

        /// Activate the shader for geometry Rendering.
        _mimapRendererShader->activate();
125
        _mimapRendererShader->setUniform("_projectionMatrix", cgt::mat4::createOrtho(0, 1, 0, 1, -1, 1));
126

127
        cgt::TextureUnit bbvUnit;
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
        bbvUnit.activate();
        _hierarchyTexture->bind();
        _mimapRendererShader->setUniform("_voxelTexture", bbvUnit.getUnitNumber());
        
        _fbo->activate();

        for (GLuint level = 0; level < _maxMipmapLevel; ++level) {
            double resX = _hierarchyTexture->getWidth() / pow(2.0, static_cast<double>(level));
            double resY = _hierarchyTexture->getHeight() / pow(2.0, static_cast<double>(level));

            _mimapRendererShader->setUniform("_level", static_cast<int>(level));

            _fbo->attachTexture(_hierarchyTexture, GL_COLOR_ATTACHMENT0, level+1, 0);
            _fbo->isComplete();

            glViewport(0, 0, static_cast<GLsizei>(resX / 2.0), static_cast<GLsizei>(resY / 2.0));
144
            _quad->render(GL_TRIANGLE_FAN);
145
146
147
148
149
150
151
152
153
154
155
156
157
158
        }

        _fbo->deactivate();
        _mimapRendererShader->deactivate();    
        LGL_ERROR;

        LDEBUG("...finished computing voxel visibilities mip maps.");
    }


    void VoxelHierarchyMapper::createEmptyTextureWithMipMaps() {
        // delete old stuff
        delete _hierarchyTexture;

159
        cgt::TextureUnit tempUnit;
160
161
162
        tempUnit.activate();

        // create new texture
163
        _hierarchyTexture = new cgt::Texture(GL_TEXTURE_2D, _dimPackedBricks, GL_RGBA32UI, cgt::Texture::NEAREST);
164
        _hierarchyTexture->setWrapping(cgt::Texture::CLAMP);
165
166
167
168
169
170
171
172
173
        LGL_ERROR;

        // attach mipmaps manually (as we want special ones)
        glBindTexture(GL_TEXTURE_2D, _hierarchyTexture->getId());

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, _maxMipmapLevel);  
174
        LGL_ERROR;
175
176
177

        int div = 2;
        for (GLuint level = 1; level <= _maxMipmapLevel; ++level) {
178
            glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA32UI, _hierarchyTexture->getWidth()/div, _hierarchyTexture->getHeight()/div, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
179
            div = div << 1;
180
            LGL_ERROR;
181
182
183
184
185
186
187
188
        }
        LGL_ERROR;
    }

    void VoxelHierarchyMapper::renderInitialHierarchy(const ImageRepresentationGL* image, AbstractTransferFunction* transferFunction) {
        LDEBUG("Start computing voxel visibilities...");

        _hierarchyRendererShader->activate();
189
        _hierarchyRendererShader->setUniform("_projectionMatrix", cgt::mat4::createOrtho(0, 1, 0, 1, -1, 1));
190
191
192
193
        _hierarchyRendererShader->setUniform("_brickSize", static_cast<GLint>(_brickSize));
        _hierarchyRendererShader->setUniform("_brickDepth", static_cast<GLint>(_brickDepth));
        _hierarchyRendererShader->setUniform("_hierarchySize", cgt::vec3(_dimPackedBricks));
        _hierarchyRendererShader->setUniform("_tfDomain", transferFunction->getVisibilityDomain());
194

195
        cgt::TextureUnit volumeUnit, tfUnit;
196
197
198
199
200
201
202
203
        image->bind(_hierarchyRendererShader, volumeUnit, "_volume", "_volumeTextureParams");
        transferFunction->bind(_hierarchyRendererShader, tfUnit, "_transferFunction", "_transferFunctionParams");

        _fbo->activate();
        _fbo->attachTexture(_hierarchyTexture, GL_COLOR_ATTACHMENT0, 0, 0);
        _fbo->isComplete();
        glViewport(0, 0, static_cast<GLsizei>(_hierarchyTexture->getWidth()), static_cast<GLsizei>(_hierarchyTexture->getHeight()));

204
        _quad->render(GL_TRIANGLE_FAN);
205
206
207
208
209
210
211
212
213

        _fbo->deactivate();
        _hierarchyRendererShader->deactivate();    

        LGL_ERROR;

        LDEBUG("...finished computing voxel visibilities.");
    }

214
    void VoxelHierarchyMapper::createXorBitmaskTexture() {
215
        cgt::TextureUnit xorUnit;
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
        xorUnit.activate();
        _xorBitmaskTexture = new cgt::Texture(GL_TEXTURE_2D, cgt::ivec3(128, 128, 1), GL_RGBA32UI, cgt::Texture::NEAREST);
        _xorBitmaskTexture->setWrapping(cgt::Texture::CLAMP);

        _xorBitmaskShader->activate();
        _fbo->activate();
        _fbo->attachTexture(_xorBitmaskTexture, GL_COLOR_ATTACHMENT0, 0, 0);
        _fbo->isComplete();
        glViewport(0, 0, 128, 128);

        _quad->render(GL_TRIANGLE_FAN);

        _fbo->deactivate();
        _xorBitmaskShader->deactivate();    
    }


233
}