Commit 18a150aa authored by schultezub's avatar schultezub
Browse files

* added ImageDataRenderTarget

 * added some initial GLSL shaders
 * work on VisualizationPipeline
 * added SliceVis pipeline stub and SliceExtractor processor stub

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@185 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent fc9111ee
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include "tgt/qt/qtcanvas.h" #include "tgt/qt/qtcanvas.h"
#include "tumvispainter.h" #include "tumvispainter.h"
#include "modules/pipelines/slicevis.h"
using namespace TUMVis; using namespace TUMVis;
...@@ -23,6 +25,9 @@ int main(int argc, char** argv) { ...@@ -23,6 +25,9 @@ int main(int argc, char** argv) {
tgt::Camera camera; tgt::Camera camera;
canvas->setCamera(&camera); canvas->setCamera(&camera);
//SliceVis sliceVis(canvas);
//canvas->setPainter(&sliceVis);
TumVisPainter painter(canvas); TumVisPainter painter(canvas);
canvas->setPainter(&painter); canvas->setPainter(&painter);
......
...@@ -14,7 +14,7 @@ namespace TUMVis { ...@@ -14,7 +14,7 @@ namespace TUMVis {
*/ */
class AbstractData { class AbstractData {
public: public:
AbstractData(); AbstractData() {};
virtual ~AbstractData() {}; virtual ~AbstractData() {};
virtual AbstractData* clone() const = 0; virtual AbstractData* clone() const = 0;
......
...@@ -75,6 +75,17 @@ namespace TUMVis { ...@@ -75,6 +75,17 @@ namespace TUMVis {
*/ */
const DataHandle* getData(const std::string& name) const; const DataHandle* getData(const std::string& name) const;
/**
* Get the DataHandle with the given name from this container and tries to dynamic_cast it to const T*.
* If no such DataHandle exists or the dynamic_cast fails, this method returns 0.
*
* \param name Key of the DataHandle to search for
* \tparam T Target type of data for dynamic_cast.
* \return The stored DataHandle with the given name, casted to const T*, 0 if no such DataHandle exists or conversion failed.
*/
template<typename T>
inline const T* getTypedData(const std::string& name) const;
private: private:
std::map<std::string, const DataHandle*> _handles; std::map<std::string, const DataHandle*> _handles;
mutable tbb::spin_mutex _localMutex; mutable tbb::spin_mutex _localMutex;
...@@ -82,6 +93,12 @@ namespace TUMVis { ...@@ -82,6 +93,12 @@ namespace TUMVis {
static const std::string loggerCat_; static const std::string loggerCat_;
}; };
template<typename T>
const T* TUMVis::DataContainer::getTypedData(const std::string& name) const {
const DataHandle* dh = getData(name);
return dynamic_cast<const T*>(dh);
}
} }
#endif // DATACONTAINER_H__ #endif // DATACONTAINER_H__
...@@ -4,7 +4,8 @@ namespace TUMVis { ...@@ -4,7 +4,8 @@ namespace TUMVis {
const std::string ImageData::loggerCat_ = "TUMVis.core.datastructures.ImageData"; const std::string ImageData::loggerCat_ = "TUMVis.core.datastructures.ImageData";
ImageData::ImageData(size_t dimensionality, const tgt::svec3& size) ImageData::ImageData(size_t dimensionality, const tgt::svec3& size)
: _dimensionality(dimensionality) : AbstractData()
, _dimensionality(dimensionality)
, _size(size) , _size(size)
, _numElements(tgt::hmul(size)) , _numElements(tgt::hmul(size))
{ {
......
#include "imagedatarendertarget.h"
#include "tgt/assert.h"
#include "tgt/gpucapabilities.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/tgt_gl.h"
namespace TUMVis {
const std::string ImageDataRenderTarget::loggerCat_ = "TUMVis.core.datastructures.ImageDataRenderTarget";
ImageDataRenderTarget::ImageDataRenderTarget(const tgt::svec3& size, GLint internalFormatColor /*= GL_RGBA8*/, GLint internalFormatDepth /*= GL_DEPTH_COMPONENT24*/)
: ImageData(2, size)
, _colorTexture(0)
, _depthTexture(0)
, _fbo(0)
{
tgtAssert(size.z == 1, "RenderTargets are only two-dimensional, expected size.z == 1.");
initRenderTarget(internalFormatColor, internalFormatDepth);
tgtAssert(_colorTexture != 0, "Color texture is 0, something went terribly wrong...");
tgtAssert(_depthTexture != 0, "Depth texture is 0, something went terribly wrong...");
tgtAssert(_fbo != 0, "Framebuffer object is 0, something went terribly wrong...");
}
ImageDataRenderTarget::~ImageDataRenderTarget() {
delete _fbo;
delete _colorTexture;
delete _depthTexture;
}
void ImageDataRenderTarget::initRenderTarget(GLint internalFormatColor, GLint internalFormatDepth) {
if (!GpuCaps.isNpotSupported() && !GpuCaps.areTextureRectanglesSupported()) {
LWARNING("Neither non-power-of-two textures nor texture rectangles seem to be supported!");
}
switch(internalFormatColor) {
case GL_RGB:
_colorTexture = new tgt::Texture(0, _size, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA16:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA16, GL_UNSIGNED_SHORT, tgt::Texture::LINEAR);
break;
case GL_RGB16F_ARB:
_colorTexture = new tgt::Texture(0, _size, GL_RGB, GL_RGB16F_ARB, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_RGBA16F_ARB:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA16F_ARB, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_RGBA32F_ARB:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA32F_ARB, GL_FLOAT, tgt::Texture::LINEAR);
break;
default:
LERROR("Unknown internal format!");
}
_colorTexture->uploadTexture();
_colorTexture->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
switch(internalFormatDepth) {
case GL_DEPTH_COMPONENT16:
_depthTexture = new tgt::Texture(0, _size, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_DEPTH_COMPONENT24:
_depthTexture = new tgt::Texture(0, _size, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_DEPTH_COMPONENT32:
_depthTexture = new tgt::Texture(0, _size, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32, GL_FLOAT, tgt::Texture::LINEAR);
break;
#ifdef GL_DEPTH_COMPONENT32F
case GL_DEPTH_COMPONENT32F:
_depthTexture = new tgt::Texture(0, _size, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F, GL_FLOAT, tgt::Texture::LINEAR);
break;
#endif
default:
LERROR("Unknown internal depth format!");
}
_depthTexture->uploadTexture();
_depthTexture->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
_fbo = new tgt::FramebufferObject();
if (!_fbo) {
LERROR("Failed to initialize framebuffer object!");
return;
}
_fbo->activate();
_fbo->attachTexture(_colorTexture);
_fbo->isComplete();
_fbo->attachTexture(_depthTexture, GL_DEPTH_ATTACHMENT_EXT);
_fbo->isComplete();
_fbo->deactivate();
}
void ImageDataRenderTarget::activate() {
_fbo->activate();
glViewport(0, 0, _size.x, _size.y);
}
void ImageDataRenderTarget::deactivate() {
_fbo->deactivate();
}
void ImageDataRenderTarget::bindColorTexture() const {
_colorTexture->bind();
}
void ImageDataRenderTarget::bindColorTexture(GLint texUnit) const {
glActiveTexture(texUnit);
_colorTexture->bind();
}
void ImageDataRenderTarget::bindDepthTexture() const {
_depthTexture->bind();
}
void ImageDataRenderTarget::bindDepthTexture(GLint texUnit) const {
glActiveTexture(texUnit);
_depthTexture->bind();
}
void ImageDataRenderTarget::bind(tgt::Shader* shader, GLint colorTexUnit /*= GL_TEXTURE0*/, GLint depthTexUnit /*= GL_TEXTURE1*/, const std::string& colorTexUniform /*= "_colorTexture"*/, const std::string& depthTexUniform /*= "_depthTexture"*/, const std::string& textureParametersUniform /*= "_textureParameters"*/) const {
bindColorTexture(colorTexUnit);
bindDepthTexture(depthTexUnit);
shader->setUniform(colorTexUniform, 0);
shader->setUniform(depthTexUniform, 1);
shader->setUniform(textureParametersUniform + "._size", tgt::vec2(_size.xy()));
shader->setUniform(textureParametersUniform + "._sizeRCP", tgt::vec2(1.f) / tgt::vec2(_size.xy()));
}
ImageDataRenderTarget* ImageDataRenderTarget::clone() const {
tgtAssert(false, "To be implemented!");
return 0;
}
ImageDataRenderTarget* ImageDataRenderTarget::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(false, "To be implemented!");
return 0;
}
}
\ No newline at end of file
#ifndef IMAGEDATARENDERTARGET_H__
#define IMAGEDATARENDERTARGET_H__
#include "tgt/framebufferobject.h"
#include "tgt/texture.h"
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
namespace tgt {
class Shader;
}
namespace TUMVis {
/**
* Stores render target data.
* This is basically a wrapper for two OpenGL textures (color + depth) and their attachment to the framebuffer.
*
* \note Its dimensionality must be 2.
*
* \todo The constructor only asserts if one of the textures or the FBO weren't successfully created.
* The member functions don't double check, whether the pointers are != 0. Make sure, that this
* is a sane design and if not, adapt the code.
*/
class ImageDataRenderTarget : public ImageData {
public:
/**
* Creates a new ImageDataRenderTarget representation.
*
* \param size Size of this image (number of elements per dimension)
* \param internalFormatColor Internal OpenGL format for the color texture.
* \param internalFormatDepth Internal OpenGL format for the depth texture.
*/
ImageDataRenderTarget(const tgt::svec3& size, GLint internalFormatColor = GL_RGBA8, GLint internalFormatDepth = GL_DEPTH_COMPONENT24);
/**
* Destructor
*/
virtual ~ImageDataRenderTarget();
/**
* \see AbstractData::clone()
**/
virtual ImageDataRenderTarget* clone() const;
/**
* \see ImageData::getSubImage
*/
virtual ImageDataRenderTarget* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
/**
* Activates the render target (binds the FBO and sets the viewport).
*/
void activate();
/**
* Deactivates the render target (unbinds the FBO).
*/
void deactivate();
/**
* Binds the color texture without activating a texture unit.
*/
void bindColorTexture() const;
/**
* Binds the depth texture without activating a texture unit.
*/
void bindDepthTexture() const;
/**
* Activates the texture unit \a texUnit and binds the color texture.
* \param texUnit Texture unit to activate
*/
void bindColorTexture(GLint texUnit) const;
/**
* Activates the texture unit \a texUnit and binds the depth texture.
* \param texUnit Texture unit to activate
*/
void bindDepthTexture(GLint texUnit) const;
void bind(
tgt::Shader* shader,
GLint colorTexUnit = GL_TEXTURE0,
GLint depthTexUnit = GL_TEXTURE1,
const std::string& colorTexUniform = "_colorTexture",
const std::string& depthTexUniform = "_depthTexture",
const std::string& textureParametersUniform = "_textureParameters") const;
protected:
/**
* Initializes the textures as well as the FBO.
* \param internalFormatColor Internal OpenGL format for the color texture.
* \param internalFormatDepth Internal OpenGL format for the depth texture.
*/
void initRenderTarget(GLint internalFormatColor, GLint internalFormatDepth);
tgt::Texture* _colorTexture; ///< color texture
tgt::Texture* _depthTexture; ///< depth texture
tgt::FramebufferObject* _fbo; ///< Framebuffer object coordinating color and depth texture
static const std::string loggerCat_;
};
}
#endif // IMAGEDATARENDERTARGET_H__
#include "tools/sampler2d.frag"
uniform sampler2D _colorTexture;
uniform sampler2D _depthTexture;
uniform TextureParameters _textureParameters;
void main() {
vec2 fragCoord = gl_FragCoord.xy * screenDimRCP_;
gl_FragData[0] = getElement2DNormalized(_colorTexture, _textureParameters, fragCoord);
gl_FragDepth = getElement2DNormalized(_depthTexture, _textureParameters, fragCoord).z;
}
void main() {
// just pass everything through to fragment shader.
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}
uniform _viewportSize;
uniform _viewportSizeRCP;
struct TextureParameters {
vec2 _size;
vec2 _sizeRCP;
};
// Texture lookup function for 2D textures,
// expecting texture coordinates as pixel coordinates, i.e, [(0,0) , textureSize].
vec4 getElement2D(in sampler2D myTexture, in TextureParameters texParams, in vec2 texCoords) {
vec2 texCoordsNormalized = texCoords * texParams.dimensionsRCP_;
vec2 texCoordsTransformed = (texParams.matrix_ * vec4(texCoordsNormalized, 0.0, 1.0)).xy;
return texture2D(myTexture, texCoordsTransformed);
}
// Texture lookup function for 2D textures,
// expecting normalized texture coordinates, i.e., [0,1].
vec4 getElement2DNormalized(in sampler2D myTexture, in TextureParameters texParams, in vec2 texCoords) {
vec2 texCoordsTransformed = (texParams.matrix_ * vec4(texCoords, 0.0, 1.0)).xy;
return texture2D(myTexture, texCoordsTransformed);
}
#include "visualizationpipeline.h" #include "visualizationpipeline.h"
#include "tgt/camera.h"
#include "tgt/quadric.h"
#include "core/datastructures/imagedatarendertarget.h"
namespace TUMVis { namespace TUMVis {
const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline"; const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline";
VisualizationPipeline::VisualizationPipeline(tgt::GLCanvas* canvas /*= 0*/) VisualizationPipeline::VisualizationPipeline(tgt::GLCanvas* canvas /*= 0*/)
: _canvas(canvas) : AbstractPipeline()
, _canvas(canvas)
, _canvasSize("canvasSize", "Canvas Size", tgt::ivec2(128, 128))
, _renderTargetID("renderTargetID", "Render Target ID", "VisualizationPipeline.renderTarget")
{ {
} }
...@@ -36,24 +42,75 @@ namespace TUMVis { ...@@ -36,24 +42,75 @@ namespace TUMVis {
void VisualizationPipeline::init() { void VisualizationPipeline::init() {
AbstractPipeline::init(); AbstractPipeline::init();
// initialize all processors:
// for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) { // TODO: Remove hardcoded paths, and use ShdrMgr.addPath() at some central location
// (*it)->initGL(); _copyShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "", false);
// }
} }
void VisualizationPipeline::paint() { void VisualizationPipeline::paint() {
// TODO: implement - is there a generic way to initiate the painting in the subclasses? if (_canvas == 0)
return;
// get OpenGL focus and setup context
_canvas->getGLFocus();
glViewport(0, 0, _canvas->getSize().x, _canvas->getSize().y);
// try get Data
const ImageDataRenderTarget* image = _data.getTypedData<ImageDataRenderTarget>(_renderTargetID.getValue());
if (image != 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate shader
_copyShader->activate();
_copyShader->setUniform("_viewportSize", tgt::vec2(_canvasSize.getValue()));
_copyShader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_canvasSize.getValue()));
// bind input textures
image->bind(_copyShader);
LGL_ERROR;
// execute the shader
//renderQuad();
_copyShader->deactivate();
LGL_ERROR;
}
else {
// TODO: render some nifty error texture
// so long, we do some dummy rendering
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
getCamera()->look();
glColor3f(1.f, 0.f, 0.f);
tgt::Sphere sphere(.5f, 64, 32);
sphere.render();
/*
// render error texture
if (!errorTex_) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
glClear(GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
errorTex_->bind();
errorTex_->enable();
glColor3f(1.f, 1.f, 1.f);
renderQuad();
errorTex_->disable();*/
}
LGL_ERROR;
} }
void VisualizationPipeline::sizeChanged(const tgt::ivec2& size) { void VisualizationPipeline::sizeChanged(const tgt::ivec2& size) {
// nothing to change if nothing changes // nothing to change if nothing changes
if (size != _canvasSize) { if (size != _canvasSize.getValue()) {
_canvasSize = size; _canvasSize.setValue(size);
// this should be enough here: Changing the property issues a notification of the
// owner (i.e. this pipeline), who is then up to decide how to proceed.
} }
// TODO: initiate pipeline evaluation, is a simple execute() what we want?
execute();
} }
} }
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
#include "tgt/glcanvas.h" #include "tgt/glcanvas.h"
#include "tgt/painter.h" #include "tgt/painter.h"
#include "tgt/shadermanager.h"
#include "tgt/event/eventlistener.h" #include "tgt/event/eventlistener.h"
#include "core/eventhandlers/abstracteventhandler.h" #include "core/eventhandlers/abstracteventhandler.h"
#include "core/pipeline/abstractpipeline.h" #include "core/pipeline/abstractpipeline.h"
#include "core/properties/genericproperty.h"
#include <vector> #include <vector>
...@@ -30,7 +32,6 @@ namespace TUMVis { ...@@ -30,7 +32,6 @@ namespace TUMVis {
/** /**
* Initializes the OpenGL context of the pipeline and its processors. * Initializes the OpenGL context of the pipeline and its processors.
* \todo merge with init() ?
* \note When overwriting this method, make sure to call the base class version first. * \note When overwriting this method, make sure to call the base class version first.
*/ */
virtual void init(); virtual void init();
...@@ -71,13 +72,12 @@ namespace TUMVis { ...@@ -71,13 +72,12 @@ namespace TUMVis {
PropertyCollection& getPropertyCollection(); PropertyCollection& getPropertyCollection();
protected: protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
tgt::GLCanvas* _canvas; ///< Target canvas for rendering tgt::GLCanvas* _canvas; ///< Target canvas for rendering
tgt::ivec2 _canvasSize; ///< Viewport size of target canvas GenericProperty<tgt::ivec2> _canvasSize; ///< Viewport size of target canvas
GenericProperty<std::string> _renderTargetID; ///< ID of the render target image to be rendered to the canvas
tgt::Shader* _copyShader; ///< Shader for copying the render target to the framebuffer.
std::vector<AbstractEventHandler*> _eventHandlers; ///< List of registered event handlers for the pipeline std::vector<AbstractEventHandler*> _eventHandlers; ///< List of registered event handlers for the pipeline
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible
static const std::string loggerCat_; static const std::string loggerCat_;
}; };
......
...@@ -8,6 +8,7 @@ namespace TUMVis { ...@@ -8,6 +8,7 @@ namespace TUMVis {
: _name(name) : _name(name)
, _title(title) , _title(title)
, _invalidationLevel(il) , _invalidationLevel(il)
, _inUse(false)
{ {
} }
...@@ -43,4 +44,15 @@ namespace TUMVis { ...@@ -43,4 +44,15 @@ namespace TUMVis {
const std::set<AbstractProperty*>& AbstractProperty::getSharedProperties() const { const std::set<AbstractProperty*>& AbstractProperty::getSharedProperties() const {
return _sharedProperties;