Commit 1d4fea74 authored by schultezub's avatar schultezub

introducing SimpleRaycaster

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@226 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 6c3588f3
......@@ -11,6 +11,7 @@ namespace TUMVis {
, _imageReader()
, _eepGenerator(_renderTargetSize)
, _drrraycater(_renderTargetSize)
, _simpleRaycaster(_renderTargetSize)
, _trackballEH(0)
{
_trackballEH = new TrackballNavigationEventHandler(&_eepGenerator._camera, _renderTargetSize.getValue());
......@@ -19,6 +20,7 @@ namespace TUMVis {
_processors.push_back(&_imageReader);
_processors.push_back(&_eepGenerator);
_processors.push_back(&_drrraycater);
_processors.push_back(&_simpleRaycaster);
}
DVRVis::~DVRVis() {
......@@ -32,10 +34,16 @@ namespace TUMVis {
_imageReader._targetImageID.setValue("reader.output");
_eepGenerator._entryImageID.addSharedProperty(&_drrraycater._entryImageID);
_eepGenerator._entryImageID.addSharedProperty(&_simpleRaycaster._entryImageID);
_eepGenerator._exitImageID.addSharedProperty(&_drrraycater._exitImageID);
_eepGenerator._exitImageID.addSharedProperty(&_simpleRaycaster._exitImageID);
_drrraycater._targetImageID.setValue("drr.output");
_drrraycater._sourceImageID.setValue("eep.input");
_simpleRaycaster._targetImageID.setValue("dvr.output");
_simpleRaycaster._sourceImageID.setValue("eep.input");
_eepGenerator._sourceImageID.setValue("eep.input");
_eepGenerator._entryImageID.setValue("eep.entry");
_eepGenerator._exitImageID.setValue("eep.exit");
......@@ -45,6 +53,7 @@ namespace TUMVis {
_imageReader.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
_eepGenerator.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
_drrraycater.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
_simpleRaycaster.s_invalidated.connect<DVRVis>(this, &DVRVis::onProcessorInvalidated);
}
void DVRVis::execute() {
......@@ -74,10 +83,14 @@ namespace TUMVis {
if (! _eepGenerator.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(_eepGenerator);
lockGLContextAndExecuteProcessor(_drrraycater);
lockGLContextAndExecuteProcessor(_simpleRaycaster);
}
if (! _eepGenerator.getInvalidationLevel().isValid() || !_drrraycater.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(_drrraycater);
}
if (! _eepGenerator.getInvalidationLevel().isValid() || !_simpleRaycaster.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(_simpleRaycaster);
}
}
const std::string DVRVis::getName() const {
......
......@@ -7,6 +7,7 @@
#include "modules/io/mhdimagereader.h"
#include "modules/vis/eepgenerator.h"
#include "modules/vis/drrraycaster.h"
#include "modules/vis/simpleraycaster.h"
namespace TUMVis {
class DVRVis : public VisualizationPipeline {
......@@ -37,6 +38,7 @@ namespace TUMVis {
MhdImageReader _imageReader;
EEPGenerator _eepGenerator;
DRRRaycaster _drrraycater;
SimpleRaycaster _simpleRaycaster;
TrackballNavigationEventHandler* _trackballEH;
};
......
......@@ -58,7 +58,7 @@ namespace TUMVis {
protected:
std::string generateHeader() const;
tgt::Shader* _shader; ///< Shader for slice rendering
tgt::Shader* _shader; ///< Shader for DRR rendering
static const std::string loggerCat_;
};
......
......@@ -70,7 +70,7 @@ namespace TUMVis {
glEnable(GL_CULL_FACE);
// create entry points texture
ImageDataRenderTarget* entrypoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
ImageDataRenderTarget* entrypoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1), GL_RGBA16F);
entrypoints->activate();
glDepthFunc(GL_LESS);
......@@ -82,7 +82,7 @@ namespace TUMVis {
entrypoints->deactivate();
// create exit points texture
ImageDataRenderTarget* exitpoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
ImageDataRenderTarget* exitpoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1), GL_RGBA16F);
exitpoints->activate();
glDepthFunc(GL_GREATER);
......
#include "simpleraycaster.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 SimpleRaycaster::loggerCat_ = "TUMVis.modules.vis.SimpleRaycaster";
SimpleRaycaster::SimpleRaycaster(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", .1f, 0.001f, 1.f)
, _jitterEntryPoints("jitterEntryPoints", "Jitter Entry Points", true)
, _shader(0)
{
addProperty(&_sourceImageID);
addProperty(&_entryImageID);
addProperty(&_exitImageID);
addProperty(&_targetImageID);
addProperty(&_transferFunction);
addProperty(&_samplingStepSize);
addProperty(&_jitterEntryPoints);
}
SimpleRaycaster::~SimpleRaycaster() {
}
void SimpleRaycaster::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/simpleraycaster.frag", "", false);
_shader->setHeaders(generateHeader());
_shader->rebuild();
}
void SimpleRaycaster::deinit() {
ShdrMgr.dispose(_shader);
_shader = 0;
VisualizationProcessor::deinit();
}
void SimpleRaycaster::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* rt = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
glPushAttrib(GL_ALL_ATTRIB_BITS);
_shader->activate();
_shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
_shader->setUniform("_jitterEntryPoints", _jitterEntryPoints.getValue());
_shader->setUniform("_samplingStepSize", _samplingStepSize.getValue());
tgt::TextureUnit volumeUnit, entryUnit, entryUnitDepth, exitUnit, exitUnitDepth, tfUnit;
img->bind(_shader, volumeUnit, "_volume");
entryPoints->bind(_shader, &entryUnit, &entryUnitDepth, "_entryPoints", "_entryPointsDepth");
exitPoints->bind(_shader, &exitUnit, &exitUnitDepth, "_exitPoints", "_exitPointsDepth");
_transferFunction.getTF()->bind(_shader, tfUnit);
rt->activate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
LGL_ERROR;
tgt::QuadRenderer::renderQuad();
LGL_ERROR;
rt->deactivate();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
glPopAttrib();
data.addData(_targetImageID.getValue(), rt);
}
else {
LERROR("Input image must have dimensionality of 3.");
}
}
else {
LERROR("No suitable input image found.");
}
_invalidationLevel.setValid();
}
std::string SimpleRaycaster::generateHeader() const {
std::string toReturn;
return toReturn;
}
}
#include "tools/raycasting.frag"
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform vec2 _viewportSizeRCP;
uniform bool _jitterEntryPoints;
uniform Texture2D _entryPoints; // ray entry points
uniform Texture2D _entryPointsDepth; // ray entry points depth
uniform Texture2D _exitPoints; // ray exit points
uniform Texture2D _exitPointsDepth; // ray exit points depth
uniform Texture3D _volume; // texture lookup parameters for volume_
uniform sampler1D _tfTex;
uniform TFParameters _tfTextureParameters;
uniform float _samplingStepSize;
// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
/**
* Computes the DRR by simple raycasting and returns the final fragment color.
*/
vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) {
vec4 result = vec4(0.0);
float depthT = -1.0;
// calculate ray parameters
vec3 direction = exitPoint.rgb - entryPoint.rgb;
float t = 0.0;
float tend = length(direction);
direction = normalize(direction);
if (_jitterEntryPoints)
jitterEntryPoint(entryPoint, direction, _samplingStepSize);
while (t < tend) {
vec3 samplePosition = entryPoint.rgb + t * direction;
float intensity = getElement3DNormalized(_volume, samplePosition).a;
vec4 color = lookupTF(_tfTextureParameters, _tfTex, intensity);
// perform compositing
if (color.a > 0.0) {
// accomodate for variable sampling rates (base interval defined by mod_compositing.frag)
color.a = 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 + (1.0 -result.a) * color.a;
}
// save first hit ray parameter for depth value calculation
if (depthT < 0.0 && result.a > 0.0)
depthT = t;
// early ray termination
if (result.a >= 1.0) {
result.a = 1.0;
t = tend;
}
t += _samplingStepSize;
}
// calculate depth value from ray parameter
gl_FragDepth = 1.0;
//if (depthT >= 0.0) {
// float depthEntry = getElement2DNormalized(_entryPointsDepth, texCoords).z;
// float depthExit = getElement2DNormalized(_exitPointsDepth, texCoords).z;
// gl_FragDepth = calculateDepthValue(depthT/tend, depthEntry, depthExit);
//}
return result;
}
/***
* The main method.
***/
void main() {
vec2 p = gl_FragCoord.xy * _viewportSizeRCP;
vec3 frontPos = getElement2DNormalized(_entryPoints, p).rgb;
vec3 backPos = getElement2DNormalized(_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] = performRaycasting(frontPos, backPos, p);
}
}
#ifndef SIMPLERAYCASTER_H__
#define SIMPLERAYCASTER_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;
/**
* Performs a simple volume ray casting.
* \todo OpenGL supports up to 4 bound FBO. We can use them to generate multiple images
* in a single pass, e.g. first hit point, normals, MIP, DVR.
* \todo Create some kind of RaycastingProcessor class to inherit from.
*/
class SimpleRaycaster : public VisualizationProcessor {
public:
/**
* Constructs a new SimpleRaycaster Processor
**/
SimpleRaycaster(GenericProperty<tgt::ivec2>& canvasSize);
/**
* Destructor
**/
virtual ~SimpleRaycaster();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "SimpleRaycaster"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Performs a simple volume ray casting."; };
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;
BoolProperty _jitterEntryPoints;
protected:
std::string generateHeader() const;
tgt::Shader* _shader; ///< Shader for raycasting
static const std::string loggerCat_;
};
}
#endif // SIMPLERAYCASTER_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