Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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

Branching work to introduce new FBO handling concept:

 * each VisualizationProcessor manages its own FBO
 * instead of creating a whole new FBO each process(), the processors shall only create and attach textures to the FBO
 * the FramebufferActivationGuard offers automatic (de)activation and detachment of all textures

SimpleRaycaster already uses the new concept, the rest still uses the legacy API
parent 63ea46dc
......@@ -45,6 +45,7 @@
#include "application/campvispainter.h"
#include "application/gui/mainwindow.h"
#include "core/datastructures/imagerepresentationrendertarget.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
#include "core/tools/quadrenderer.h"
......@@ -106,10 +107,13 @@ namespace campvis {
// ensure matching OpenGL specs
if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_3) {
LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intendet.");
LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intended.");
}
if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intendet.");
LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
}
if (!GpuCaps.isNpotSupported() && !GpuCaps.areTextureRectanglesSupported()) {
LERROR("Neither non-power-of-two textures nor texture rectangles seem to be supported. CAMPVis will probably not work as intended.");
}
QuadRenderer::init();
......
......@@ -39,7 +39,7 @@
#include "core/datastructures/imagerepresentationgl.h"
namespace campvis {
const std::string ImageRepresentationRenderTarget::loggerCat_ = "CAMPVis.core.datastructures.ImageRepresentationRenderTarget";
ImageRepresentationRenderTarget* ImageRepresentationRenderTarget::create(ImageData* parent, GLint internalFormatColor /*= GL_RGBA8*/, GLint internalFormatDepth /*= GL_DEPTH_COMPONENT24*/) {
......@@ -55,6 +55,19 @@ namespace campvis {
return std::make_pair(id, toReturn);
}
ImageRepresentationRenderTarget* ImageRepresentationRenderTarget::create(ImageData* parent, const tgt::FramebufferObject* fbo) {
ImageRepresentationRenderTarget* toReturn = new ImageRepresentationRenderTarget(parent, fbo);
toReturn->addToParent();
return toReturn;
}
std::pair<ImageData*, ImageRepresentationRenderTarget*> ImageRepresentationRenderTarget::createWithImageData(const tgt::svec2& size, const tgt::FramebufferObject* fbo) {
ImageData* id = new ImageData(2, tgt::svec3(size, 1), 4);
ImageRepresentationRenderTarget* toReturn = new ImageRepresentationRenderTarget(id, fbo);
toReturn->addToParent();
return std::make_pair(id, toReturn);
}
ImageRepresentationRenderTarget::ImageRepresentationRenderTarget(ImageData* parent, GLint internalFormatColor /*= GL_RGBA8*/, GLint internalFormatDepth /*= GL_DEPTH_COMPONENT24*/)
: GenericAbstractImageRepresentation<ImageRepresentationRenderTarget>(parent)
, _colorTextures(0)
......@@ -63,10 +76,6 @@ namespace campvis {
{
tgtAssert(parent->getSize().z == 1, "RenderTargets are only two-dimensional, expected parent image size.z == 1.");
if (!GpuCaps.isNpotSupported() && !GpuCaps.areTextureRectanglesSupported()) {
LWARNING("Neither non-power-of-two textures nor texture rectangles seem to be supported!");
}
_fbo = new tgt::FramebufferObject();
if (!_fbo) {
LERROR("Failed to initialize framebuffer object!");
......@@ -113,6 +122,23 @@ namespace campvis {
// _fbo->attachTexture(cc, GL_COLOR_ATTACHMENT0);
}
ImageRepresentationRenderTarget::ImageRepresentationRenderTarget(ImageData* parent, const tgt::FramebufferObject* fbo)
: GenericAbstractImageRepresentation<ImageRepresentationRenderTarget>(parent)
, _colorTextures(0)
, _depthTexture(0)
, _fbo(0)
{
tgtAssert(parent->getSize().z == 1, "RenderTargets are only two-dimensional, expected parent image size.z == 1.");
tgt::Texture *const *const attachments = fbo->getAttachments();
for (size_t i = 0; i < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS; ++i) {
if (attachments[i] != 0)
_colorTextures.push_back(attachments[i]);
}
if (attachments[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS] != 0)
_depthTexture = attachments[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS];
}
ImageRepresentationRenderTarget::~ImageRepresentationRenderTarget() {
// TODO: double check whether deleting FBOs without detaching their attachments is not harmful
// if (_fbo != 0) {
......@@ -346,4 +372,7 @@ namespace campvis {
}
}
\ No newline at end of file
......@@ -31,22 +31,29 @@
#define IMAGEREPRESENTATIONRENDERTARGET_H__
#include "tgt/framebufferobject.h"
#include "tgt/singleton.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "tgt/vector.h"
#include "core/datastructures/genericabstractimagerepresentation.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "tbb/atomic.h"
#include "tbb/spin_mutex.h"
#include <list>
#include <utility>
#include <vector>
namespace tgt {
class Shader;
class FramebufferObject;
}
namespace campvis {
class ImageRepresentationGL;
class ImageRepresentationRenderTarget;
/**
* Stores render target data.
* This is basically a wrapper for multiple OpenGL textures (color + depth) and their attachment to the framebuffer.
......@@ -70,7 +77,7 @@ namespace campvis {
* \param internalFormatColor Internal OpenGL format for the color texture.
* \param internalFormatDepth Internal OpenGL format for the depth texture.
* \return A pointer to the newly created ImageRepresentationRenderTarget, you do \b not own this pointer!
*/
*/
static ImageRepresentationRenderTarget* create(ImageData* parent, GLint internalFormatColor = GL_RGBA8, GLint internalFormatDepth = GL_DEPTH_COMPONENT24);
/**
......@@ -84,6 +91,32 @@ namespace campvis {
*/
static std::pair<ImageData*, ImageRepresentationRenderTarget*> createWithImageData(const tgt::svec2& size, GLint internalFormatColor = GL_RGBA8, GLint internalFormatDepth = GL_DEPTH_COMPONENT24);
/**
* Creates a new ImageRepresentationRenderTarget representation with one color and one depth attachment
* and automatically adds it to \a parent which will take ownerwhip.
*
* \note You do \b not own the returned pointer..
* \note ImageRepresentationRenderTarget will take ownership of all textures attached to \a fbo.
*
* \param parent Image this representation represents, must not be 0.
* \param fbo FrameBufferObject to use the attachements from.
* \return A pointer to the newly created ImageRepresentationRenderTarget, you do \b not own this pointer!
*/
static ImageRepresentationRenderTarget* create(ImageData* parent, const tgt::FramebufferObject* fbo);
/**
* Creates a new ImageRepresentationRenderTarget and a new ImageData with the given specifications.
* Assigns the representation to the image.
*
* \note ImageRepresentationRenderTarget will take ownership of all textures attached to \a fbo.
*
* \param parent Image this representation represents, must not be 0.
* \param fbo FrameBufferObject to use the attachements from.
*
* \return A pair of the created ImageData and the created RenderTarget image representation.
*/
static std::pair<ImageData*, ImageRepresentationRenderTarget*> createWithImageData(const tgt::svec2& size, const tgt::FramebufferObject* fbo);
/**
* Destructor
*/
......@@ -212,11 +245,20 @@ namespace campvis {
/**
* Creates a new ImageRepresentationRenderTarget from one color texture and one optional depth texture.
* \param parent Image this representation represents, must not be 0.
* \param colorTexture Color texture, must not be 0
* \param depthTexture Depth texture, optional, must have valid internal format and same dimensions as \a colorTexture
*/
ImageRepresentationRenderTarget(ImageData* parent, const ImageRepresentationGL* colorTexture, const ImageRepresentationGL* depthTexture = 0);
/**
* Creates a new ImageRepresentationRenderTarget from one color texture and one optional depth texture.
* \note ImageRepresentationRenderTarget will take ownership of all textures attached to \a fbo.
* \param parent Image this representation represents, must not be 0.
* \param fbo FrameBufferObject to use the attachements from.
*/
ImageRepresentationRenderTarget(ImageData* parent, const tgt::FramebufferObject* fbo);
/**
* Activates the texture unit \a texUnit and binds the color texture.
* \param texUnit Texture unit to activate
......
......@@ -29,10 +29,19 @@
#include "visualizationprocessor.h"
#include "tgt/textureunit.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationrendertarget.h"
namespace campvis {
const std::string VisualizationProcessor::loggerCat_ = "CAMPVis.core.datastructures.VisualizationProcessor";
// ================================================================================================
VisualizationProcessor::VisualizationProcessor(IVec2Property& renderTargetSize)
: AbstractProcessor()
, _fbo(0)
, _renderTargetSize("renderTargetSize", "Canvas Size", renderTargetSize.getValue(), renderTargetSize.getMinValue(), renderTargetSize.getMaxValue())
{
renderTargetSize.addSharedProperty(&_renderTargetSize);
......@@ -43,4 +52,122 @@ namespace campvis {
}
void VisualizationProcessor::init() {
AbstractProcessor::init();
_fbo = new tgt::FramebufferObject();
}
void VisualizationProcessor::deinit() {
_fbo->detachAll();
delete _fbo;
AbstractProcessor::deinit();
}
void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, GLenum attachment) {
tgtAssert(_fbo->isActive(), "Trying to attach a texture while FBO is not bound!");
// acqiure a new TextureUnit, so that we don't mess with other currently bound textures during texture upload...
tgt::TextureUnit rtUnit;
rtUnit.activate();
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create texture
tgt::Texture* tex = 0;
switch(internalFormat) {
case GL_RGB:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGB16F_ARB:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGB, GL_RGB16F_ARB, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_RGBA:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA8:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA16:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGBA, GL_RGBA16, GL_UNSIGNED_SHORT, tgt::Texture::LINEAR);
break;
case GL_RGBA16F:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGBA, GL_RGBA16F, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_RGBA32F:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_RGBA, GL_RGBA32F, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_DEPTH_COMPONENT16:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_FLOAT, tgt::Texture::LINEAR);
break;
case GL_DEPTH_COMPONENT24:
tex = new tgt::Texture(0, getRenderTargetSize(), GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_FLOAT, tgt::Texture::LINEAR);
break;
#ifdef GL_DEPTH_COMPONENT32F
case GL_DEPTH_COMPONENT32F:
break;
#endif
default:
tgtAssert(false, "Unknown internal format!");
}
tex->uploadTexture();
tex->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
// attach texture to FBO
_fbo->attachTexture(tex, attachment);
}
void VisualizationProcessor::createAndAttachTexture(GLint internalFormat) {
GLenum attachment = 0;
switch(internalFormat) {
case GL_RGB:
case GL_RGB16F_ARB:
case GL_RGBA:
case GL_RGBA8:
case GL_RGBA16:
case GL_RGBA16F:
case GL_RGBA32F:
if (_fbo->getNumColorAttachments() >= static_cast<size_t>(GpuCaps.getMaxColorAttachments())) {
tgtAssert(false, "Tried to attach more color textures to FBO than supported!");
LWARNING("Tried to attach more color textures to FBO than supported, aborted.");
return;
}
attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + _fbo->getNumColorAttachments());
break;
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
#ifdef GL_DEPTH_COMPONENT32F
case GL_DEPTH_COMPONENT32F:
#endif
tgtAssert(_fbo->getDepthAttachment() == 0, "Tried to attach more than one depth texture.");
attachment = GL_DEPTH_ATTACHMENT;
break;
default:
tgtAssert(false, "Unknown internal format!");
}
createAndAttachTexture(internalFormat, attachment);
}
tgt::ivec3 VisualizationProcessor::getRenderTargetSize() const {
return tgt::ivec3(_renderTargetSize.getValue(), 1);
}
void VisualizationProcessor::createAndAttachColorTexture() {
createAndAttachTexture(GL_RGBA8);
}
void VisualizationProcessor::createAndAttachDepthTexture() {
createAndAttachTexture(GL_DEPTH_COMPONENT24);
}
ImageData* VisualizationProcessor::createImageDataFromFbo() const {
ImageData* toReturn = new ImageData(2, getRenderTargetSize(), 4);
ImageRepresentationRenderTarget::create(toReturn, _fbo);
return toReturn;
}
}
......@@ -30,24 +30,51 @@
#ifndef VISUALIZATIONPROCESSOR_H__
#define VISUALIZATIONPROCESSOR_H__
#include "tgt/framebufferobject.h"
#include "tgt/texture.h"
#include "tgt/vector.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/properties/numericproperty.h"
namespace campvis {
class ImageData;
/**
* Specialization of AbstractProcessor for visualization purposes.
*
* VisualizationProcessors are required to be called by a VisualizationPipeline which ensure
* to provide a valid OpenGL context when calling the processor's process() method. Hence, a
* VisualizationProcessor is allowed/capable of performing OpenGl operations.
* For determining the canvas/viewport size, a VisualizationProcessor gets a reference to the
* parent pipeline's render target size property during instantiation.
*
* Each VisualizationProcessor has its own OpenGL FramebufferObject, which is created during
* init(). For determining the canvas/viewport size, a VisualizationProcessor gets a reference
* to the parent pipeline's render target size property during instantiation.
*
* \sa VisualizationPipeline
*/
class VisualizationProcessor : public AbstractProcessor {
public:
struct FramebufferActivationGuard {
public:
FramebufferActivationGuard(VisualizationProcessor* vp)
: _parentProcessor(vp)
, _fbo(vp->_fbo)
{
tgtAssert(_fbo != 0, "FBO must not be 0.");
_fbo->activate();
}
~FramebufferActivationGuard() {
_fbo->detachAll();
_fbo->deactivate();
}
private:
VisualizationProcessor* _parentProcessor;
tgt::FramebufferObject* _fbo;
};
/**
* Creates a VisualizationProcessor.
......@@ -62,11 +89,55 @@ namespace campvis {
**/
virtual ~VisualizationProcessor();
/// \see AbstractProcessor::init()
virtual void init();
/// \see AbstractProcessor::deinit()
virtual void deinit();
/**
* Creates a texture with the given format and attaches it to the FBO to \a attachment.
* \param internalFormat Internal OpenGL texture format
* \param attachment Target attachment for texture
*/
void createAndAttachTexture(GLint internalFormat, GLenum attachment);
/**
* Creates a texture with the given format and attaches it to the FBO using the default attachments.
* \note Default attachment are GL_DEPTH_ATTACHMENT for depth textures and
* GL_COLOR_ATTACHMENT_0 + <number of color textures attached>.
* \param internalFormat Internal OpenGL texture format
*/
void createAndAttachTexture(GLint internalFormat);
/**
* Creates a color texture with format GL_RGBA8 and attaches it to the FBO using the
* default attachment.
*/
void createAndAttachColorTexture();
/**
* Creates a depth texture with format GL_DEPTH_COMPONENT24 and attaches it to the FBO
* using the default attachment.
*/
void createAndAttachDepthTexture();
//protected:
// protected:
/**
* Creates an ImageData object from the textures currently attached to the FBO.
* \note The caller takes ownership of the returned pointer.
* \return A pointer to the created ImageData object.
*/
ImageData* createImageDataFromFbo() const;
tgt::ivec3 getRenderTargetSize() const;
tgt::FramebufferObject* _fbo;
IVec2Property _renderTargetSize; ///< Viewport size of target canvas
static const std::string loggerCat_;
};
}
......
......@@ -32,7 +32,9 @@ const std::string FramebufferObject::loggerCat_("tgt.FramebufferObject");
FramebufferObject::FramebufferObject()
: id_(0)
, numColorAttachments_(0)
{
memset(attachments_, 0, sizeof(Texture*) * (TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS+2));
generateId();
}
......@@ -67,22 +69,24 @@ void FramebufferObject::attachTexture(Texture* texture, GLenum attachment, int m
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, texture->getType(), texture->getId(), mipLevel );
break;
}
attachedTextures_[attachment] = texture;
size_t index = decodeAttachment(attachment);
attachments_[index] = texture;
if (index < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS)
++numColorAttachments_;
}
Texture* FramebufferObject::getTextureAtAttachment(GLenum attachment) {
std::map<GLenum, Texture*>::iterator iter = attachedTextures_.find(attachment);
if( iter != attachedTextures_.end() ) {
return attachedTextures_[attachment];
}
else
return 0;
return attachments_[decodeAttachment(attachment)];
}
void FramebufferObject::detachTexture(GLenum attachment) {
std::map<GLenum, Texture*>::iterator iter = attachedTextures_.find(attachment);
if( iter != attachedTextures_.end() ) {
attachedTextures_.erase(iter);
size_t index = decodeAttachment(attachment);
if (attachments_[index] != 0) {
attachments_[index] = 0;
if (index < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS)
--numColorAttachments_;
}
else {
LWARNING("Trying to detach unknown texture!");
......@@ -92,9 +96,16 @@ void FramebufferObject::detachTexture(GLenum attachment) {
}
void FramebufferObject::detachAll() {
while(!attachedTextures_.empty()) {
detachTexture(attachedTextures_.begin()->first);
for (GLenum i = 0; i < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS; ++i) {
if (colorAttachments_[i] != 0)
detachTexture(GL_COLOR_ATTACHMENT0 + i);
}
if (depthAttachment_ != 0)
detachTexture(GL_DEPTH_ATTACHMENT);
if (stencilAttachment_ != 0)
detachTexture(GL_STENCIL_ATTACHMENT);
numColorAttachments_ = 0;
}
bool FramebufferObject::isComplete() const
......@@ -149,4 +160,25 @@ GLuint FramebufferObject::generateId() {
return id_;
}
Texture*const *const FramebufferObject::getAttachments() const {
return attachments_;
}
const Texture* FramebufferObject::getColorAttachment(size_t index /*= 0*/) const {
tgtAssert(index < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS, "Index out of bounds!");
return attachments_[index];
}
const Texture* FramebufferObject::getDepthAttachment() const {
return attachments_[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS];
}
const Texture* FramebufferObject::getStencilAttachment() const {
return attachments_[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS+1];
}
size_t FramebufferObject::getNumColorAttachments() const {
return numColorAttachments_;
}
} // namespace
......@@ -25,6 +25,10 @@
#ifndef TGT_FRAMEBUFFEROBJECT_H
#define TGT_FRAMEBUFFEROBJECT_H
/// if you run out of FBO color attachments, edit this value o_O
#define TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS 6
#include "tgt/assert.h"
#include "tgt/texture.h"
#include "tgt/types.h"
......@@ -46,7 +50,7 @@ public:
/// Bind a texture to the "attachment" point of this FBO
void attachTexture(Texture* texture,
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT,
GLenum attachment = GL_COLOR_ATTACHMENT0,
int mipLevel = 0,
int zSlice = 0);
......@@ -60,12 +64,42 @@ public:
GLuint getId() const { return id_; };
Texture *const *const getAttachments() const;
size_t getNumColorAttachments() const;
const Texture* getColorAttachment(size_t index = 0) const;
const Texture* getDepthAttachment() const;
const Texture* getStencilAttachment() const;
protected:
GLuint generateId();
GLuint id_;
std::map<GLenum, Texture*> attachedTextures_;
size_t decodeAttachment(GLenum attachment) {
switch (attachment) {
case GL_DEPTH_ATTACHMENT:
return TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS;
case GL_STENCIL_ATTACHMENT:
return TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS + 1;
default:
tgtAssert((attachment - GL_COLOR_ATTACHMENT0) < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS, "Color attachments out of bounds - adjust TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS define!");
return attachment - GL_COLOR_ATTACHMENT0;
}
}
union {
struct {
Texture* colorAttachments_[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS];
Texture* depthAttachment_;
Texture* stencilAttachment_;
};
Texture* attachments_[TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS+2];
};
size_t numColorAttachments_;
static const std::string loggerCat_; ///< category used in logging
};
......
......@@ -57,12 +57,13 @@ namespace campvis {
}
void SimpleRaycaster::processImpl(DataContainer& data, ImageRepresentationGL::ScopedRepresentation& image) {
std::pair<ImageData*, ImageRepresentationRenderTarget*> output = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
output.second->createAndAttachTexture(GL_RGBA32F);
output.second->createAndAttachTexture(GL_RGBA32F);
output.second->activate();
FramebufferActivationGuard fag(this);
createAndAttachTexture(GL_RGBA8);
createAndAttachTexture(GL_RGBA32F);
createAndAttachTexture(GL_RGBA32F);
createAndAttachDepthTexture();
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
static const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, buffers);