Commit 47d3a104 authored by schultezub's avatar schultezub
Browse files

Introducing DRRRaycaster

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@221 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 030250bf
...@@ -10,6 +10,7 @@ namespace TUMVis { ...@@ -10,6 +10,7 @@ namespace TUMVis {
: VisualizationPipeline() : VisualizationPipeline()
, _imageReader() , _imageReader()
, _eepGenerator(_renderTargetSize) , _eepGenerator(_renderTargetSize)
, _drrraycater(_renderTargetSize)
, _trackballEH(0) , _trackballEH(0)
{ {
_trackballEH = new TrackballNavigationEventHandler(&_eepGenerator._camera, _renderTargetSize.getValue()); _trackballEH = new TrackballNavigationEventHandler(&_eepGenerator._camera, _renderTargetSize.getValue());
...@@ -17,6 +18,7 @@ namespace TUMVis { ...@@ -17,6 +18,7 @@ namespace TUMVis {
_processors.push_back(&_imageReader); _processors.push_back(&_imageReader);
_processors.push_back(&_eepGenerator); _processors.push_back(&_eepGenerator);
_processors.push_back(&_drrraycater);
} }
DVRVis::~DVRVis() { DVRVis::~DVRVis() {
...@@ -29,15 +31,21 @@ namespace TUMVis { ...@@ -29,15 +31,21 @@ namespace TUMVis {
_imageReader._url.setValue("D:\\Medical Data\\smallHeart.mhd"); _imageReader._url.setValue("D:\\Medical Data\\smallHeart.mhd");
_imageReader._targetImageID.setValue("reader.output"); _imageReader._targetImageID.setValue("reader.output");
_eepGenerator._entryImageID.addSharedProperty(&_drrraycater._entryImageID);
_eepGenerator._exitImageID.addSharedProperty(&_drrraycater._exitImageID);
_drrraycater._targetImageID.setValue("drr.output");
_drrraycater._sourceImageID.setValue("eep.input");
_eepGenerator._sourceImageID.setValue("eep.input"); _eepGenerator._sourceImageID.setValue("eep.input");
_eepGenerator._entryImageID.setValue("eep.entry"); _eepGenerator._entryImageID.setValue("eep.entry");
_eepGenerator._exitImageID.setValue("eep.exit"); _eepGenerator._exitImageID.setValue("eep.exit");
_renderTargetID.setValue("eep.entry"); _renderTargetID.setValue("drr.output");
//_renderTargetID.addSharedProperty(&(_eepGenerator._entryImageID)); //_renderTargetID.addSharedProperty(&(_eepGenerator._entryImageID));
_imageReader.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated); _imageReader.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
_eepGenerator.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated); _eepGenerator.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
_drrraycater.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
} }
void DVRVis::execute() { void DVRVis::execute() {
...@@ -70,6 +78,9 @@ namespace TUMVis { ...@@ -70,6 +78,9 @@ namespace TUMVis {
if (! _eepGenerator.getInvalidationLevel().isValid()) { if (! _eepGenerator.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(_eepGenerator); lockGLContextAndExecuteProcessor(_eepGenerator);
} }
if (! _drrraycater.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(_drrraycater);
}
} }
const std::string DVRVis::getName() const { const std::string DVRVis::getName() const {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "core/pipeline/visualizationpipeline.h" #include "core/pipeline/visualizationpipeline.h"
#include "modules/io/mhdimagereader.h" #include "modules/io/mhdimagereader.h"
#include "modules/vis/eepgenerator.h" #include "modules/vis/eepgenerator.h"
#include "modules/vis/drrraycaster.h"
namespace TUMVis { namespace TUMVis {
class DVRVis : public VisualizationPipeline { class DVRVis : public VisualizationPipeline {
...@@ -35,6 +36,7 @@ namespace TUMVis { ...@@ -35,6 +36,7 @@ namespace TUMVis {
protected: protected:
MhdImageReader _imageReader; MhdImageReader _imageReader;
EEPGenerator _eepGenerator; EEPGenerator _eepGenerator;
DRRRaycaster _drrraycater;
TrackballNavigationEventHandler* _trackballEH; TrackballNavigationEventHandler* _trackballEH;
}; };
......
#include "drrraycaster.h"
#include "tgt/logmanager.h"
#include "tgt/quadrenderer.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagedatagl.h"
#include "core/datastructures/imagedatarendertarget.h"
#include "core/datastructures/imagedataconverter.h"
#include "core/classification/simpletransferfunction.h"
namespace TUMVis {
const std::string DRRRaycaster::loggerCat_ = "TUMVis.modules.vis.DRRRaycaster";
DRRRaycaster::DRRRaycaster(GenericProperty<tgt::ivec2>& canvasSize)
: VisualizationProcessor(canvasSize)
, _sourceImageID("sourceImageID", "Input Image", "")
, _entryImageID("entryImageID", "Output Entry Points Image", "")
, _exitImageID("exitImageID", "Output Exit Points Image", "")
, _targetImageID("targetImageID", "Output Image", "")
, _transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
, _samplingStepSize("samplingStepSize", "Sampling Step Size", .5f, 0.01f, 2.f)
, _shift("shift", "Normalization Shift", 0.f, -10.f, 10.f)
, _scale("scale", "Normalization Scale", 1.f, 0.f, 1000.f)
, _invertMapping("invertMapping", "Invert Mapping", false, InvalidationLevel::INVALID_RESULT | InvalidationLevel::INVALID_SHADER)
, _shader(0)
{
addProperty(&_sourceImageID);
addProperty(&_entryImageID);
addProperty(&_exitImageID);
addProperty(&_targetImageID);
addProperty(&_transferFunction);
addProperty(&_samplingStepSize);
addProperty(&_shift);
addProperty(&_scale);
addProperty(&_invertMapping);
}
DRRRaycaster::~DRRRaycaster() {
}
void DRRRaycaster::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/drrraycaster.frag", "", false);
}
void DRRRaycaster::deinit() {
ShdrMgr.dispose(_shader);
_shader = 0;
VisualizationProcessor::deinit();
}
void DRRRaycaster::process(DataContainer& data) {
DataContainer::ScopedTypedData<ImageDataGL> img(data, _sourceImageID.getValue());
DataContainer::ScopedTypedData<ImageDataRenderTarget> entryPoints(data, _entryImageID.getValue());
DataContainer::ScopedTypedData<ImageDataRenderTarget> exitPoints(data, _exitImageID.getValue());
if (img != 0 && entryPoints != 0 && exitPoints != 0) {
if (img->getDimensionality() == 3) {
if (_invalidationLevel.isInvalidShader()) {
_shader->setHeaders(generateHeader());
_shader->rebuild();
}
ImageDataRenderTarget* output = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
_shader->activate();
_shader->setUniform("_samplingStepSize", _samplingStepSize.getValue());
_shader->setUniform("_shift", _shift.getValue());
_shader->setUniform("_scale", _scale.getValue());
tgt::TextureUnit volumeUnit, entryUnit, exitUnit, tfUnit;
img->bind(_shader, volumeUnit, "_volume");
entryPoints->bind(_shader, &entryUnit, 0, "_entryPoints", "", "_entryParameters");
exitPoints->bind(_shader, &exitUnit, 0, "_exitPoints", "", "_exitParameters");
_transferFunction.getTF()->bind(_shader, tfUnit);
output->activate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
tgt::QuadRenderer::renderQuad();
output->deactivate();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
data.addData(_targetImageID.getValue(), output);
}
else {
LERROR("Input image must have dimensionality of 3.");
}
}
else {
LERROR("No suitable input image found.");
}
_invalidationLevel.setValid();
}
std::string DRRRaycaster::generateHeader() const {
std::string toReturn;
if (_invertMapping.getValue())
toReturn += "#define DRR_INVERT 1\n";
// if (depthMapping_.get())
// header +="#define DEPTH_MAPPING 1\n";
return toReturn;
}
}
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform vec2 _viewportSize;
uniform vec2 _viewportSizeRCP;
uniform Texture2D _entryPoints; // ray entry points
uniform Texture2D _exitPoints; // ray exit points
uniform Texture3D _volume; // texture lookup parameters for volume_
uniform sampler1D _tfTex;
uniform TFParameters _tfTextureParameters;
uniform float _samplingStepSize;
uniform float _shift;
uniform float _scale;
// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
/***
* Performs direct volume rendering and
* returns the final fragment color.
***/
vec4 raycastDRR(in vec3 first, in vec3 last, vec2 p) {
vec4 result = vec4(0.0);
bool finished = false;
// calculate ray parameters
float stepIncr = _samplingStepSize;
float tend;
float t = 0.0;
vec3 direction = last.rgb - first.rgb;
tend = length(direction);
direction = normalize(direction);
// 2 nested loops allow for more than 255 iterations,
// but is slower than while (t < tend)
for (int loop0=0; !finished && loop0<255; loop0++) {
for (int loop1=0; !finished && loop1<255; loop1++) {
vec3 samplePosition = first.rgb + t * direction;
vec4 voxel = getElement3D(_volume, samplePosition);
vec4 color = lookupTF(_tfTextureParameters, _tfTex, voxel.a);
#ifdef DEPTH_MAPPING
// use Bernstein Polynomials for depth-color mapping
float depth = t / tend;
float b02 = (1-depth) * (1-depth);
float b12 = 2 * depth * (1-depth);
float b22 = depth * depth;
color = vec4(0.75*b02 + 0.25*b12, b12, 0.25*b12 + 0.75*b22, 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP));
/* float t_sq = depth * depth;
float inv_t_sq = (1-depth) * (1-depth);
float b04 = inv_t_sq * inv_t_sq;
float b24 = 6 * t_sq * inv_t_sq;
float b44 = t_sq * t_sq;
color = vec4(0.5*b04 + 0.5*b24, b24, 0.5*b24 + 0.5*b44, 1.0 - pow(1.0 - color.a, samplingStepSize_ * SAMPLING_BASE_INTERVAL_RCP));*/
result.rgb = result.rgb + (1.0 - result.a) * color.a * color.rgb;
result.a = result.a + color.a * _scale;
#else
// perform compositing (account for differen step size / sampling rate)
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
result.a = result.a + color.a * _scale;
#endif
t += stepIncr;
finished = finished || (t > tend);
}
}
// DRR images don't have a meaningful depth value
gl_FragDepth = 1.0;
#ifdef DEPTH_MAPPING
result.rgb = result.rgb * vec3(exp(-result.a + _shift));
//result.rgb = exp(-result.rgb * result.a + shift_);
#else
#ifdef DRR_INVERT
// apply e-function, as we want the "negative" X-Ray image, we invert the intensity result
result.rgb = 1 - vec3(exp(-result.a + _shift));
#else
// apply e-function, the normal way
result.rgb = vec3(exp(-result.a + _shift));
#endif
#endif
result.a = 1.0;
return result;
}
/***
* The main method.
***/
void main() {
vec2 p = gl_FragCoord.xy * _viewportSizeRCP;
vec3 frontPos = getElement2D(_entryPoints, p).rgb;
vec3 backPos = getElement2D(_exitPoints, p).rgb;
//determine whether the ray has to be casted
if (frontPos == backPos) {
//background need no raycasting
discard;
} else {
//fragCoords are lying inside the boundingbox
gl_FragData[0] = raycastDRR(frontPos, backPos, p);
}
}
#ifndef DRRRAYCASTER_H__
#define DRRRAYCASTER_H__
#include <string>
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/genericproperty.h"
#include "core/properties/numericproperty.h"
#include "core/properties/transferfunctionproperty.h"
namespace tgt {
class Shader;
}
namespace TUMVis {
class ImageData;
/**
* Creates a Digitally Reconstructed Radiograph.
*/
class DRRRaycaster : public VisualizationProcessor {
public:
/**
* Constructs a new DRRRaycaster Processor
**/
DRRRaycaster(GenericProperty<tgt::ivec2>& canvasSize);
/**
* Destructor
**/
virtual ~DRRRaycaster();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "DRRRaycaster"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Creates a Digitally Reconstructed Radiograph."; };
virtual void process(DataContainer& data);
GenericProperty<std::string> _sourceImageID; ///< image ID for input image
GenericProperty<std::string> _entryImageID; ///< image ID for output entry points image
GenericProperty<std::string> _exitImageID; ///< image ID for output exit points image
GenericProperty<std::string> _targetImageID; ///< image ID for output image
TransferFunctionProperty _transferFunction; ///< Transfer function
FloatProperty _samplingStepSize;
FloatProperty _shift;
FloatProperty _scale;
BoolProperty _invertMapping;
protected:
std::string generateHeader() const;
tgt::Shader* _shader; ///< Shader for slice rendering
static const std::string loggerCat_;
};
}
#endif // DRRRAYCASTER_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