// ================================================================================================ // // This file is part of the CAMPVis Software Framework. // // If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved, // Christian Schulte zu Berge // Chair for Computer Aided Medical Procedures // Technische Universitaet Muenchen // Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 "laoraycaster.h" #include "core/tools/quadrenderer.h" #include "core/datastructures/lightsourcedata.h" #include "core/datastructures/cameradata.h" #include "core/datastructures/renderdata.h" #include "core/datastructures/genericimagerepresentationlocal.h" #include "core/datastructures/facegeometry.h" #include "core/pipeline/processordecoratorgradient.h" #include "core/classification/geometry1dtransferfunction.h" #include namespace campvis { const std::string LAORaycaster::loggerCat_ = "CAMPVis.modules.advrc.LAORaycaster"; LAORaycaster::LAORaycaster(IVec2Property* viewportSizeProp) : RaycastingProcessor(viewportSizeProp, "modules/advancedraycasting/glsl/laoraycaster.frag", true) , p_enableShading("EnableShading", "Enable Shading", false) , p_aoRays("AORays", "Number of directional samples", 8, 0, 50) , p_aoSamples("AOSamples", "Number of Samples per ray (controls size of AO sphere)", 10, 0, 80) , p_aoSphereRadius("AOSphereRadius", "AO Sphere Radius [voxels]", 8.0f, 0.1f, 50.0f, 0.25f) , p_aoOpacityScale("OpacityScale", "Opacity Scaling", 1.0f, 0.0f, 5.f) , p_aoEffectGamma("AOEffectGamma", "AO Scale Gamma", 1.0f, .0f, 5.f) , p_aoEmissiveTransferFunction("AOTransferFunction", "Emissive Transfer Function", new Geometry1DTransferFunction(128)) , p_aoEmissiveScale("EmissiveScale", "Emissive Color Scaling", 1.0f, 0.0f, 10.f) , p_lightId("LightId", "Input Light Source", "lightsource", DataNameProperty::READ) , p_quadGeometry("QuadGeometry", "Quad Geometry", "", DataNameProperty::READ) { addDecorator(new ProcessorDecoratorGradient()); addProperty(p_enableShading, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER); addProperty(p_aoRays, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER); addProperty(p_aoSamples, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER); addProperty(p_aoSphereRadius); addProperty(p_aoOpacityScale); addProperty(p_aoEffectGamma); addProperty(p_aoEmissiveTransferFunction); addProperty(p_aoEmissiveScale); addProperty(p_lightId); addProperty(p_quadGeometry); decoratePropertyCollection(this); } LAORaycaster::~LAORaycaster() { } void LAORaycaster::init() { RaycastingProcessor::init(); } void LAORaycaster::deinit() { RaycastingProcessor::deinit(); } void LAORaycaster::processImpl(DataContainer& data, ImageRepresentationGL::ScopedRepresentation& image) { ScopedTypedData light(data, p_lightId.getValue()); ScopedTypedData outputImage(data, p_targetImageID.getValue()); ScopedTypedData quadGeometry(data, p_quadGeometry.getValue(), true); ScopedTypedData cam(data, p_camera.getValue()); if (p_enableShading.getValue() == false || light != nullptr) { auto aotf = p_aoEmissiveTransferFunction.getTF(); cgt::TextureUnit aoTFUnit; aotf->bind(_shader, aoTFUnit, "_aoEmissiveTF", "_aoEmissiveTFParams"); FramebufferActivationGuard fag(this); createAndAttachTexture(GL_RGBA8, &outputImage); createAndAttachTexture(GL_RGBA32F, &outputImage); createAndAttachTexture(GL_RGBA32F, &outputImage); createAndAttachDepthTexture(&outputImage); static const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, buffers); if (p_enableShading.getValue() && light != nullptr) { light->bind(_shader, "_lightSource"); } _shader->setUniform("_aoSphereRadius", p_aoSphereRadius.getValue()); _shader->setUniform("_aoGamma", p_aoEffectGamma.getValue()); _shader->setUniform("_aoEmissiveScale", p_aoEmissiveScale.getValue()); _shader->setUniform("_aoOpacityScale", p_aoOpacityScale.getValue()); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (quadGeometry && cam) { _shader->setUniform("_viewMatrix", cam->getCamera().getViewMatrix()); _shader->setUniform("_projectionMatrix", cam->getCamera().getProjectionMatrix()); quadGeometry->render(GL_TRIANGLE_FAN); } else { QuadRdr.renderQuad(); } // restore state glDrawBuffers(1, buffers); glDisable(GL_DEPTH_TEST); LGL_ERROR; data.addData(p_targetImageID.getValue(), new RenderData(_fbo)); } else { LDEBUG("Could not load light source from DataContainer."); } } std::string LAORaycaster::generateHeader() const { std::string toReturn = RaycastingProcessor::generateHeader(); if (p_enableShading.getValue()) toReturn += "#define ENABLE_SHADING\n"; toReturn += "#define NUM_AO_RAYS " + std::to_string(p_aoRays.getValue()) + "\n"; toReturn += "#define NUM_AO_RAY_STEPS " + std::to_string(p_aoSamples.getValue()) + "\n"; return toReturn; } void LAORaycaster::updateProperties(DataContainer& dataContainer) { RaycastingProcessor::updateProperties(dataContainer); p_lightId.setVisible(p_enableShading.getValue()); p_aoEmissiveTransferFunction.setVisible(p_aoEmissiveScale.getValue() > 0); } }