Commit b44fd851 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'slicerenderer2d' into 'development'

Slicerenderer2d

slice renderer that applies transfer function, clips image and/or inverts axes.
tested only with grayscale input images, but should support color and images as well.
parents 0eca23ec 0ad0a40c
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// 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.
//
// ================================================================================================
in vec3 ex_TexCoord;
in vec4 ex_Color;
out vec4 out_Color;
//#include "tools/background.frag"
#include "tools/texture2d.frag"
#include "tools/transferfunction.frag"
uniform sampler2D _texture;
uniform TextureParameters2D _textureParams;
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
uniform mat4 _texCoordsMatrix;
uniform vec2 _topLeft;
uniform vec2 _bottomRight;
void main() {
vec2 tex = _topLeft + ex_TexCoord.xy * (_bottomRight - _topLeft);
vec4 texel = texture(_texture, tex);
if (_textureParams._numChannels == 1) {
out_Color = lookupTF(_transferFunction, _transferFunctionParams, texel.r);
}
else if (_textureParams._numChannels == 3) {
out_Color = vec4(abs(texel.rgb), 1.0);
}
else if (_textureParams._numChannels == 4) {
out_Color = (abs(texel) - vec4(_transferFunctionParams._intensityDomain.x)) / (_transferFunctionParams._intensityDomain.y - _transferFunctionParams._intensityDomain.x);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// 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 "slicerenderer2d.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "tgt/event/mouseevent.h"
#include "core/datastructures/facegeometry.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/pipeline/processordecoratorbackground.h"
#include "core/classification/simpletransferfunction.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string SliceRenderer2D::loggerCat_ = "CAMPVis.modules.vis.SliceRenderer2D";
SliceRenderer2D::SliceRenderer2D(IVec2Property* viewportSizeProp)
: VisualizationProcessor(viewportSizeProp)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
, p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
, p_invertXAxis("invert_x", "Invert X Axis", false)
, p_invertYAxis("invert_y", "Invert Y Axis", false)
, p_cropTop("crop_top", "Crop Top Pixels", 0, 0, 512)
, p_cropLeft("crop_left", "Crop Left Pixels", 0, 0, 512)
, p_cropBottom("crop_bottom", "Crop Bottom Pixels", 0, 0, 512)
, p_cropRight("crop_right", "Crop Right Pixels", 0, 0, 512)
, p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
, _shader(0)
, _lastImgSize(0,0,0)
{
addProperty(p_sourceImageID, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_targetImageID);
addProperty(p_transferFunction);
addProperty(p_cropTop, INVALID_RESULT);
addProperty(p_cropLeft, INVALID_RESULT);
addProperty(p_cropBottom, INVALID_RESULT);
addProperty(p_cropRight, INVALID_RESULT);
addProperty(p_invertXAxis, INVALID_RESULT);
addProperty(p_invertYAxis, INVALID_RESULT);
}
SliceRenderer2D::~SliceRenderer2D() {
}
void SliceRenderer2D::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/slicerenderer2d.frag", "");
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
void SliceRenderer2D::deinit() {
VisualizationProcessor::deinit();
ShdrMgr.dispose(_shader);
}
void SliceRenderer2D::updateResult(DataContainer& data) {
ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
if (img != 0) {
if (img->getDimensionality() == 2) {
tgt::vec3 imgSize(img->getSize());
float renderTargetRatio = static_cast<float>(getEffectiveViewportSize().x) / static_cast<float>(getEffectiveViewportSize().y);
float sliceRatio = 1.f;
tgt::vec2 topLeft_px(p_cropLeft.getValue(), p_cropTop.getValue());
tgt::vec2 bottomRight_px(imgSize.x - p_cropRight.getValue(), imgSize.y - p_cropBottom.getValue());
tgt::vec2 croppedSize = bottomRight_px - topLeft_px;
sliceRatio =
(static_cast<float>(croppedSize.x) * img.getImageData()->getMappingInformation().getVoxelSize().x)
/ (static_cast<float>(croppedSize.y) * img.getImageData()->getMappingInformation().getVoxelSize().y);
// configure model matrix so that slices are rendered with correct aspect posNormalized
float ratioRatio = sliceRatio / renderTargetRatio;
tgt::mat4 viewMatrix = (ratioRatio > 1) ? tgt::mat4::createScale(tgt::vec3(1.f, 1.f / ratioRatio, 1.f)) : tgt::mat4::createScale(tgt::vec3(ratioRatio, 1.f, 1.f));
viewMatrix.t11 *= -1;
tgt::mat4 originalViewMatrix = viewMatrix;
// prepare OpenGL
_shader->activate();
tgt::TextureUnit inputUnit, tfUnit;
img->bind(_shader, inputUnit);
p_transferFunction.getTF()->bind(_shader, tfUnit);
if (p_invertXAxis.getValue())
viewMatrix *= tgt::mat4::createScale(tgt::vec3(-1, 1, 1));
if (p_invertYAxis.getValue())
viewMatrix *= tgt::mat4::createScale(tgt::vec3(1, -1, 1));
tgt::vec2 topLeft = topLeft_px / imgSize.xy();
tgt::vec2 bottomRight = bottomRight_px / imgSize.xy();
_shader->setUniform("_viewMatrix", viewMatrix);
_shader->setUniform("_topLeft", topLeft);
_shader->setUniform("_bottomRight", bottomRight);
// render slice
FramebufferActivationGuard fag(this);
createAndAttachColorTexture();
createAndAttachDepthTexture();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
}
else {
LERROR("Input image must have dimensionality of 2.");
}
}
else {
LERROR("No suitable input image found.");
}
validate(INVALID_RESULT);
}
void SliceRenderer2D::updateProperties(DataContainer& dc) {
ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
p_transferFunction.setImageHandle(img.getDataHandle());
if (img != 0)
{
tgt::svec3 size = img->getSize();
/// NOTE: the setMaxValue calls create crashes, probably due to qt threading issues
// it is a lot more stable with this _lastImgSize check
if (size.x != _lastImgSize.x || size.y != _lastImgSize.y)
{
p_cropTop.setMaxValue(size.y);
p_cropBottom.setMaxValue(size.y);
p_cropLeft.setMaxValue(size.x);
p_cropRight.setMaxValue(size.x);
_lastImgSize = size;
}
}
validate(AbstractProcessor::INVALID_PROPERTIES);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// 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.
//
// ================================================================================================
#ifndef SLICERENDERER2D_H__
#define SLICERENDERER2D_H__
#include <string>
#include "tgt/buffer.h"
#include "tgt/vertexarrayobject.h"
#include "tgt/event/eventlistener.h"
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/optionproperty.h"
#include "core/properties/numericproperty.h"
#include "core/properties/transferfunctionproperty.h"
namespace tgt {
class Shader;
}
namespace campvis {
/**
* Applies a transfer function and other modifiers to a 2D input image and renders to screen buffer
*/
class SliceRenderer2D : public VisualizationProcessor, public tgt::EventListener {
public:
/**
* Constructs a new SliceRenderer2D Processor
**/
SliceRenderer2D(IVec2Property* viewportSizeProp);
/**
* Destructor
**/
virtual ~SliceRenderer2D();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "SliceRenderer2D"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Applies a transfer function and other modifiers to a 2D input image"; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Jakob Weiss <weissj@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::TESTING; };
DataNameProperty p_sourceImageID; ///< image ID for input image
DataNameProperty p_targetImageID; ///< image ID for output image
BoolProperty p_invertXAxis; ///< inverts the x axis (horizontal) of the image
BoolProperty p_invertYAxis; ///< inverts the y axis (vertical) of the image
IntProperty p_cropTop; ///< number of pixels to crop from the top
IntProperty p_cropLeft; ///< number of pixels to crop from the left
IntProperty p_cropBottom; ///< number of pixels to crop from the bottom
IntProperty p_cropRight; ///< number of pixels to crop from the right
TransferFunctionProperty p_transferFunction; ///< Transfer function
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer);
tgt::Shader* _shader; ///< Shader for slice rendering
static const std::string loggerCat_;
private:
tgt::svec3 _lastImgSize;
};
}
#endif // SLICERENDERER2D_H__
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment