Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

geometryrenderer.cpp 12.6 KB
Newer Older
schultezub's avatar
schultezub committed
1 2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
schultezub's avatar
schultezub committed
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
schultezub's avatar
schultezub committed
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".
schultezub's avatar
schultezub committed
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
schultezub's avatar
schultezub committed
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.
schultezub's avatar
schultezub committed
22 23 24 25 26
// 
// ================================================================================================

#include "geometryrenderer.h"

27 28 29 30
#include "cgt/glmath.h"
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
schultezub's avatar
schultezub committed
31

32
#include "core/datastructures/cameradata.h"
33
#include "core/datastructures/imagedata.h"
34
#include "core/datastructures/lightsourcedata.h"
35
#include "core/datastructures/renderdata.h"
36
#include "core/datastructures/imagerepresentationgl.h"
schultezub's avatar
schultezub committed
37 38
#include "core/datastructures/meshgeometry.h"

schultezub's avatar
schultezub committed
39
namespace campvis {
40 41 42 43 44 45 46 47 48 49
    static const GenericOption<GLenum> renderOptions[7] = {
        GenericOption<GLenum>("points", "GL_POINTS", GL_POINTS),
        GenericOption<GLenum>("lines", "GL_LINES", GL_LINES),
        GenericOption<GLenum>("linestrip", "GL_LINE_STRIP", GL_LINE_STRIP),
        GenericOption<GLenum>("triangles", "GL_TRIANGLES", GL_TRIANGLES),
        GenericOption<GLenum>("trianglefan", "GL_TRIANGLE_FAN", GL_TRIANGLE_FAN),
        GenericOption<GLenum>("trianglestrip", "GL_TRIANGLE_STRIP", GL_TRIANGLE_STRIP),
        GenericOption<GLenum>("polygon", "GL_POLYGON", GL_POLYGON)
    };

50 51 52 53 54 55
    static const GenericOption<GeometryRenderer::ColoringMode> coloringOptions[3] = {
        GenericOption<GeometryRenderer::ColoringMode>("GeometryColor", "Original Geometry Color", GeometryRenderer::GEOMETRY_COLOR),
        GenericOption<GeometryRenderer::ColoringMode>("SolidColor", "Solid Color", GeometryRenderer::SOLID_COLOR),
        GenericOption<GeometryRenderer::ColoringMode>("TextureColor", "Color from Texture Lookup", GeometryRenderer::TEXTURE_COLOR),
    };

schultezub's avatar
schultezub committed
56
    const std::string GeometryRenderer::loggerCat_ = "CAMPVis.modules.vis.GeometryRenderer";
schultezub's avatar
schultezub committed
57

58 59
    GeometryRenderer::GeometryRenderer(IVec2Property* viewportSizeProp)
        : VisualizationProcessor(viewportSizeProp)
60
        , p_geometryID("geometryID", "Input Geometry ID", "gr.input", DataNameProperty::READ)
61
        , p_textureID("TextureId", "Input Texture ID (optional)", "gr.inputtexture", DataNameProperty::READ)
62
        , p_camera("Camera", "Camera ID", "camera", DataNameProperty::READ)
63
        , p_renderTargetID("p_renderTargetID", "Output Image", "gr.output", DataNameProperty::WRITE)
64 65
        , p_enableShading("EnableShading", "Enable Shading", true)
        , p_lightId("LightId", "Input Light Source", "lightsource", DataNameProperty::READ)
66 67
        , p_renderMode("RenderMode", "Render Mode", renderOptions, 7)
        , p_coloringMode("ColoringMode", "ColoringMode", coloringOptions, 3)
68
        , p_solidColor("SolidColor", "Solid Color", cgt::vec4(1.f, .5f, 0.f, 1.f), cgt::vec4(0.f), cgt::vec4(1.f))
69 70
        , p_pointSize("PointSize", "Point Size", 3.f, .1f, 10.f)
        , p_lineWidth("LineWidth", "Line Width", 1.f, .1f, 10.f)
71
        , p_showWireframe("ShowWireframe", "Show Wireframe", true)
72
        , p_wireframeColor("WireframeColor", "Wireframe Color", cgt::vec4(1.f, 1.f, 1.f, 1.f), cgt::vec4(0.f), cgt::vec4(1.f))
73 74
        , _pointShader(0)
        , _meshShader(0)
schultezub's avatar
schultezub committed
75
    {
76 77
        p_coloringMode.selectByOption(SOLID_COLOR);

78 79 80
        addProperty(p_geometryID);
        addProperty(p_textureID);
        addProperty(p_camera);
81
        addProperty(p_renderTargetID);
82

83 84 85
        addProperty(p_enableShading, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
        addProperty(p_lightId);

86 87 88
        addProperty(p_renderMode, INVALID_RESULT | INVALID_PROPERTIES);
        addProperty(p_coloringMode, INVALID_RESULT | INVALID_SHADER | INVALID_PROPERTIES);
        addProperty(p_solidColor);
89

90 91 92 93
        addProperty(p_pointSize);
        addProperty(p_lineWidth);
        addProperty(p_showWireframe, INVALID_RESULT | INVALID_SHADER | INVALID_PROPERTIES);
        addProperty(p_wireframeColor);
schultezub's avatar
schultezub committed
94 95 96 97 98 99 100 101
    }

    GeometryRenderer::~GeometryRenderer() {

    }

    void GeometryRenderer::init() {
        VisualizationProcessor::init();
102
        _pointShader = ShdrMgr.load("modules/vis/glsl/geometryrenderer.vert", "modules/vis/glsl/geometryrenderer.frag", generateGlslHeader(false));
103
        _meshShader = ShdrMgr.load("modules/vis/glsl/geometryrenderer.vert", "modules/vis/glsl/geometryrenderer.geom", "modules/vis/glsl/geometryrenderer.frag", generateGlslHeader(true));
schultezub's avatar
schultezub committed
104 105 106
    }

    void GeometryRenderer::deinit() {
107 108
        ShdrMgr.dispose(_pointShader);
        _pointShader = 0;
109 110 111
        ShdrMgr.dispose(_meshShader);
        _meshShader = 0;

schultezub's avatar
schultezub committed
112 113 114
        VisualizationProcessor::deinit();
    }

115
    void GeometryRenderer::updateResult(DataContainer& data) {
116
        ScopedTypedData<GeometryData> proxyGeometry(data, p_geometryID.getValue());
117
        ScopedTypedData<LightSourceData> light(data, p_lightId.getValue());
118
        ScopedTypedData<CameraData> camera(data, p_camera.getValue());
119 120
        ScopedTypedData<RenderData> rd(data, p_textureID.getValue(), true);
        ImageRepresentationGL::ScopedRepresentation repGl(data, p_textureID.getValue(), true);
121 122 123 124 125 126 127 128

        const ImageRepresentationGL* texture = nullptr;
        if (p_coloringMode.getOptionValue() == TEXTURE_COLOR) {
            if (proxyGeometry->hasTextureCoordinates()) {
                if (rd != nullptr && rd->getNumColorTextures() > 0)
                    texture = rd->getColorTexture()->getRepresentation<ImageRepresentationGL>();
                else if (repGl != nullptr)
                    texture = repGl;
129 130
                else
                    LERROR("Could not find suitable texture in DataConatiner.");
131 132 133 134 135
            }
            else {
                LERROR("Cannot use textured rendering since input geometry has no texture coordinates!");
            }
        }
schultezub's avatar
schultezub committed
136

137 138
        if (proxyGeometry != nullptr
            && camera != nullptr
139 140
            && (p_enableShading.getValue() == false || light != nullptr)
            && (p_coloringMode.getOptionValue() != TEXTURE_COLOR || texture != nullptr) 
141
            && _pointShader != nullptr && _meshShader != nullptr)
142
            {
143
            // select correct shader
144
            cgt::Shader* leShader = nullptr;
145 146 147 148 149 150
            if (p_renderMode.getOptionValue() == GL_POINTS || p_renderMode.getOptionValue() == GL_LINES || p_renderMode.getOptionValue() == GL_LINE_STRIP)
                leShader = _pointShader;
            else
                leShader = _meshShader;

            // calculate viewport matrix for NDC -> viewport conversion
151 152
            cgt::vec2 halfViewport = cgt::vec2(getEffectiveViewportSize()) / 2.f;
            cgt::mat4 viewportMatrix = cgt::mat4::createTranslation(cgt::vec3(halfViewport, 0.f)) * cgt::mat4::createScale(cgt::vec3(halfViewport, 1.f));
153 154

            leShader->activate();
155 156

            // bind texture if needed
157
            cgt::TextureUnit tut, narf, blub, textureUnit;
158 159 160 161 162
            tut.activate();
            if (texture != nullptr)
                texture->bind(leShader, textureUnit, "_texture", "_textureParams");

            // set modelview and projection matrices
163
            leShader->setIgnoreUniformLocationError(true);
164 165 166 167 168
            
            if (p_enableShading.getValue() && light != nullptr) {
                light->bind(leShader, "_lightSource");
            }

169 170
            leShader->setUniform("_projectionMatrix", camera->getCamera().getProjectionMatrix());
            leShader->setUniform("_viewMatrix", camera->getCamera().getViewMatrix());
171 172 173 174
            leShader->setUniform("_viewportMatrix", viewportMatrix);

            leShader->setUniform("_computeNormals", proxyGeometry->getNormalsBuffer() == 0);

175
            leShader->setUniform("_coloringMode", p_coloringMode.getValue());
176 177 178 179
            leShader->setUniform("_solidColor", p_solidColor.getValue());
            leShader->setUniform("_wireframeColor", p_wireframeColor.getValue());
            leShader->setUniform("_lineWidth", p_lineWidth.getValue());

180
            leShader->setUniform("_cameraPosition", camera->getCamera().getPosition());
181 182
            leShader->setIgnoreUniformLocationError(false);

183 184 185
            FramebufferActivationGuard fag(this);
            createAndAttachColorTexture();
            createAndAttachDepthTexture();
schultezub's avatar
schultezub committed
186

187 188 189 190 191 192
            static const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
            if (proxyGeometry->hasPickingInformation()) {
                createAndAttachColorTexture();
                glDrawBuffers(3, buffers);
            }

193 194
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
195
            glEnable(GL_DEPTH_TEST);
schultezub's avatar
schultezub committed
196 197 198
            glDepthFunc(GL_LESS);
            glClearDepth(1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
199 200
            if (p_renderMode.getOptionValue() == GL_POINTS)
                glPointSize(p_pointSize.getValue());
201 202
            else if (p_renderMode.getOptionValue() == GL_LINES || p_renderMode.getOptionValue() == GL_LINE_STRIP)
                glLineWidth(p_lineWidth.getValue());
203

204
            proxyGeometry->render(p_renderMode.getOptionValue());
schultezub's avatar
schultezub committed
205

206 207
            if (p_renderMode.getOptionValue() == GL_POINTS)
                glPointSize(1.f);
208 209 210
            else if (p_renderMode.getOptionValue() == GL_LINES || p_renderMode.getOptionValue() == GL_LINE_STRIP)
                glLineWidth(1.f);

211 212 213 214 215

            if (proxyGeometry->hasPickingInformation()) {
                glDrawBuffers(1, buffers);
            }

216
            leShader->deactivate();
217
            glDepthFunc(GL_LESS);
218
            glDisable(GL_DEPTH_TEST);
219
            glDisable(GL_BLEND);
schultezub's avatar
schultezub committed
220 221
            LGL_ERROR;

222
            data.addData(p_renderTargetID.getValue(), new RenderData(_fbo));
schultezub's avatar
schultezub committed
223 224
        }
        else {
225
            LDEBUG("No suitable input data found.");
schultezub's avatar
schultezub committed
226 227 228
        }
    }

229
    std::string GeometryRenderer::generateGlslHeader(bool hasGeometryShader) const {
230 231 232 233
        std::string toReturn;

        if (p_enableShading.getValue())
            toReturn += "#define ENABLE_SHADING\n";
234

235
        if (hasGeometryShader && p_showWireframe.getValue())
236 237 238 239 240
            toReturn += "#define WIREFRAME_RENDERING\n";

        if (hasGeometryShader)
            toReturn += "#define HAS_GEOMETRY_SHADER\n";

241 242 243
        if (p_coloringMode.getOptionValue() == TEXTURE_COLOR)
            toReturn += "#define ENABLE_TEXTURING\n";

244 245 246
        return toReturn;
    }

247
    void GeometryRenderer::updateShader() {
248 249 250 251
        _pointShader->setHeaders(generateGlslHeader(false));
        _pointShader->rebuild();
        _meshShader->setHeaders(generateGlslHeader(true));
        _meshShader->rebuild();
252 253
    }

254
    void GeometryRenderer::updateProperties(DataContainer& dataContainer) {
255
        p_solidColor.setVisible(p_coloringMode.getOptionValue() == SOLID_COLOR);
256
        p_lightId.setVisible(p_enableShading.getValue());
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

        switch (p_renderMode.getOptionValue()) {
            case GL_POINTS:
                p_pointSize.setVisible(true);
                p_lineWidth.setVisible(false);
                p_showWireframe.setVisible(false);
                break;
            case GL_LINES: // fallthrough
            case GL_LINE_STRIP:
                p_pointSize.setVisible(false);
                p_lineWidth.setVisible(true);
                p_showWireframe.setVisible(false);
                break;
            case GL_TRIANGLES: // fallthrough
            case GL_TRIANGLE_FAN: // fallthrough
            case GL_TRIANGLE_STRIP: // fallthrough
            case GL_POLYGON:
                p_pointSize.setVisible(false);
                p_lineWidth.setVisible(p_showWireframe.getValue());
                p_showWireframe.setVisible(true);
                break;
        }

        p_wireframeColor.setVisible(p_showWireframe.getValue());
    }

schultezub's avatar
schultezub committed
283
}