Commit 04b3c253 authored by Janis Born's avatar Janis Born

implement prototype for LocationMappings-based configuration of VAO, SP, FBO

parent ff41ea3a
......@@ -54,8 +54,11 @@ public:
public:
virtual SharedRenderObject create(void)
{
SharedRenderObject renderObject(new RenderObject(mpVertexBufferObject, mpShaderProgramObject, mpFrameBufferObject));
return renderObject;
// TODO: reimplement
//SharedRenderObject renderObject(new RenderObject(mpVertexBufferObject, mpShaderProgramObject, mpFrameBufferObject));
//return renderObject;
return SharedRenderObject();
}
// =================================================================================================== \/
......
......@@ -30,6 +30,8 @@
#include <ACGL/OpenGL/Tools.hh>
#include <ACGL/OpenGL/Objects/RenderBuffer.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
#include <ACGL/OpenGL/Objects/LocationMappings.hh>
#include <vector>
#include <map>
......@@ -58,6 +60,7 @@ public:
std::string name;
ConstSharedTexture texture;
ConstSharedRenderBuffer renderBuffer;
int_t fragDataLocation; // the frag data location that maps to this attachment
};
// ===================================================================================================== \/
......@@ -74,10 +77,13 @@ public:
: mObjectName(0),
mDrawBuffers(0),
mColorAttachments(),
mColorAttachmentIndices(),
mFragDataLocationIndices(),
mDepthAttachment()
{
glGenFramebuffers(1, &mObjectName);
if (openGLCriticalErrorOccured() ) {
if (openGLCriticalErrorOccured() )
{
ACGL::Utils::error() << "could not generate FrameBufferObject!" << std::endl;
return;
}
......@@ -119,6 +125,8 @@ public:
openGLRareError(); // glBindFramebuffer can only fail if the object name is no valid FBO which shouldn't happen using this framework
}
// TODO: deprecate?
/*
inline void bindAsRenderTarget(GLenum _type = GL_FRAMEBUFFER) const
{
glBindFramebuffer(_type, mObjectName);
......@@ -126,7 +134,6 @@ public:
openGLRareError();
}
/*
inline void bindAsRenderTarget(GLint _x, GLint _y, GLsizei _w, GLsizei _h, GLenum _type = GL_FRAMEBUFFER) const
{
glBindFramebuffer(_type, mObjectName);
......@@ -146,23 +153,28 @@ public:
inline bool attachColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer)
{
bind();
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
if (openGLCommonErrorOccured()) {
Utils::error() << "Attaching of texture to the FBO failed" << std::endl;
if (openGLCommonErrorOccured())
{
Utils::error() << "Attaching of render buffer to the FBO failed" << std::endl;
return false;
}
Attachment attachment = {_name, SharedTexture(), _renderBuffer};
mColorAttachments.push_back(attachment);
mColorAttachmentIndices[_name] = mDrawBuffers;
mFragDataLocationIndices[mDrawBuffers] = mDrawBuffers;
mDrawBuffers++;
return true;
}
inline bool attachColorTexture(const std::string _name, const ConstSharedTexture& _texture)
{
bind();
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, _texture->getTarget(), _texture->getObjectName(), 0 );
if (openGLCommonErrorOccured()) {
if (openGLCommonErrorOccured())
{
Utils::error() << "Attaching of texture to the FBO failed" << std::endl;
return false;
}
......@@ -170,6 +182,7 @@ public:
Attachment attachment = {_name, _texture, SharedRenderBuffer()};
mColorAttachments.push_back(attachment);
mColorAttachmentIndices[_name] = mDrawBuffers;
mFragDataLocationIndices[mDrawBuffers] = mDrawBuffers;
mDrawBuffers++;
return true;
}
......@@ -218,6 +231,22 @@ public:
return true;
}
// =================================================================================================== \/
// =========================================================================================== METHODS \/
// =================================================================================================== \/
public:
//! updates the attachment locations of this FBO so they match the locations of fragment shader output
//! variables of the same names in _shaderPorgram
void setAttachmentsByShaderProgram(ConstSharedShaderProgram _shaderProgram);
//! sets the attachment locations of this FBO where they match the names specified in _locationMappings
void setAttachmentLocations(ConstSharedLocationMappings _locationMappings);
protected:
//! maps the frag data locations specified in mFragDataLocationIndices to the respective color attachments
void updateDrawBuffers();
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
......@@ -225,8 +254,10 @@ protected:
GLuint mObjectName;
GLsizei mDrawBuffers;
AttachmentVec mColorAttachments;
//stores the attachment index (GL_COLOR_ATTACHMENT0 + i) of each color attachment by its name.
std::map<std::string, int> mColorAttachmentIndices;
std::map<std::string, int> mColorAttachmentIndices; // maps color attachment names to attachment indices (GL_COLOR_ATTACHMENT0 + i)
std::map<int, int> mFragDataLocationIndices; // maps fragment data locations to attachment indices (GL_COLOR_ATTACHMENT0 + i)
Attachment mDepthAttachment; // depth and stencil are combined
};
......
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012, Computer Graphics Group RWTH Aachen University //
// All rights reserved. //
////////////////////////////////////////////////////////////////////////////////
#ifndef ACGL_OPENGL_OBJECTS_LOCATIONMAPPINGS_HH
#define ACGL_OPENGL_OBJECTS_LOCATIONMAPPINGS_HH
#include <map>
#include <string>
#include <ACGL/ACGL.hh>
#include <ACGL/Base/Macros.hh>
namespace ACGL{
namespace OpenGL{
class LocationMappings
{
ACGL_NOT_COPYABLE(LocationMappings)
// ===================================================================================================== \/
// ============================================================================================ TYPEDEFS \/
// ===================================================================================================== \/
public:
typedef std::map< std::string, int_t > LocationMap;
// ========================================================================================================= \/
// ============================================================================================ CONSTRUCTORS \/
// ========================================================================================================= \/
public:
LocationMappings()
: mMappings()
{ }
~LocationMappings()
{ }
// ==================================================================================================== \/
// ============================================================================================ GETTERS \/
// ==================================================================================================== \/
public:
inline int_t getLocation(const std::string& _name) const
{
if(exists(_name))
{
return mMappings.at(_name);
}
else
{
return -1;
}
}
inline const LocationMap& getLocations() const { return mMappings; }
// ==================================================================================================== \/
// ============================================================================================ SETTERS \/
// ==================================================================================================== \/
public:
inline void setLocation(const std::string& _name, int_t _location)
{
if(exists(_name))
{
ACGL::Utils::warning() << "LocationMappings: Overwriting location mapping for " << _name;
ACGL::Utils::warning() << " (previous value: " << mMappings[_name] << ", new value: " << _location<< ")" << std::endl;
}
mMappings[_name] = _location;
}
// ==================================================================================================== \/
// ============================================================================================ METHODS \/
// ==================================================================================================== \/
public:
//! Tells whether a mapping for a given name exists
inline bool exists(const std::string& _name) const { mMappings.find(_name) != mMappings.end(); }
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
protected:
LocationMap mMappings;
};
ACGL_SHARED_TYPEDEF(LocationMappings)
} // OpenGL
} // ACGL
#endif // ACGL_OPENGL_OBJECTS_LOCATIONMAPPINGS_HH
......@@ -26,6 +26,13 @@
#include <ACGL/OpenGL/GL.hh>
#if (ACGL_OPENGL_VERSION >= 30)
#include <ACGL/OpenGL/Objects/VertexArrayObject.hh>
#include <ACGL/OpenGL/Objects/ShaderProgramObject.hh>
#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
#include <ACGL/OpenGL/Objects/Viewport.hh>
/*
#include <vector>
#include <string>
#include <tr1/memory>
......@@ -160,6 +167,94 @@ ACGL_SHARED_TYPEDEF(RenderObject)
} // OpenGL
} // ACGL
*/
namespace ACGL {
namespace OpenGL {
class RenderObject
{
ACGL_NOT_COPYABLE(RenderObject)
// ========================================================================================================= \/
// ============================================================================================ CONSTRUCTORS \/
// ========================================================================================================= \/
public:
RenderObject(ConstSharedVertexArrayObject _vertexArrayObject,
ConstSharedShaderProgramObject _shaderProgramObject,
ConstSharedFrameBufferObject _frameBufferObject = ConstSharedFrameBufferObject(),
ConstSharedViewport _viewport = ConstSharedViewport())
: mpVertexArrayObject(_vertexArrayObject),
mpShaderProgramObject(_shaderProgramObject),
mpFrameBufferObject(_frameBufferObject),
mpViewport(_viewport)
{
updateMappings();
}
// ==================================================================================================== \/
// ============================================================================================ GETTERS \/
// ==================================================================================================== \/
public:
inline ConstSharedVertexArrayObject getVertexArrayObject() const { return mpVertexArrayObject; }
inline ConstSharedFrameBufferObject getFrameBufferObject() const { return mpFrameBufferObject; }
inline ConstSharedShaderProgramObject getShaderProgramObject() const { return mpShaderProgramObject; }
inline ConstSharedViewport getViewport() const { return mpViewport; }
// ==================================================================================================== \/
// ============================================================================================ METHODS \/
// ==================================================================================================== \/
public:
//! Assigns the attribute locations of the VAO to the locations of the ShaderProgram where there are matching names
void updateMappings();
void bindFrameBufferObject() const;
void useShaderProgramObject() const;
void enableVertexArrayObject() const;
void disableVertexArrayObject() const;
void useViewport() const;
inline void enable() const
{
bindFrameBufferObject();
useShaderProgramObject();
enableVertexArrayObject();
useViewport();
}
inline void disable() const
{
disableVertexArrayObject();
}
inline void draw() const
{
mpVertexArrayObject->draw();
}
inline void render() const
{
enable();
draw();
disable();
}
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
protected:
ConstSharedVertexArrayObject mpVertexArrayObject;
ConstSharedShaderProgramObject mpShaderProgramObject;
ConstSharedFrameBufferObject mpFrameBufferObject;
ConstSharedViewport mpViewport;
};
ACGL_SHARED_TYPEDEF(RenderObject)
}
}
#endif
#endif // ACGL_OPENGL_OBJECTS_RENDEROBJECT_HH
......@@ -46,6 +46,8 @@
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
//#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
#include <ACGL/OpenGL/Objects/LocationMappings.hh>
#include <ACGL/Math/Math.hh>
#include <vector>
......@@ -57,6 +59,9 @@ namespace OpenGL{
class VertexArrayObject;
ACGL_SHARED_TYPEDEF(VertexArrayObject)
class FrameBufferObject;
ACGL_SHARED_TYPEDEF(FrameBufferObject)
class ShaderProgram
{
ACGL_NOT_COPYABLE(ShaderProgram)
......@@ -120,7 +125,16 @@ public:
// ===================================================================================================== \/
public:
//! Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _vao
void setAttributeLocationsByVAO( const SharedVertexArrayObject& _vao );
void setAttributeLocationsByVAO( ConstSharedVertexArrayObject _vao );
//! Matches the fragment data locations of this ShaderProgram to the names of the color attachments of _fbo
void setFragmentDataLocationsByFBO( ConstSharedFrameBufferObject _fbo );
//! Sets the attribute locations of this ShaderProgram according to the mappings specified in
void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
//! Sets the fragment data locations of this ShaderProgram according to the mappings specified in
void setFragmentDataLocations( ConstSharedLocationMappings _locationMappings );
// ===================================================================================================== \/
// ============================================================================================ UNIFORMS \/
......
......@@ -256,6 +256,7 @@ public:
*/
void setAttributeLocationsByShaderProgram( const SharedShaderProgram &_shaderProgram )
{
// TODO: deprecate
bool fullUpdateNeeded = false;
for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
......@@ -298,6 +299,55 @@ public:
}
}
/**
* Query the attribute locations based on the attribute names in the ArrayBuffers and the ShaderProgram
* If they match, use the location reported from the ShaderProgram.
*/
void setAttributeLocations( ConstSharedLocationMappings _locationMappings )
{
bool fullUpdateNeeded = false;
for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
{
std::string attributeName = mAttributes[i].arrayBuffer->getAttributes()[ mAttributes[i].attributeID ].name;
int_t location = _locationMappings->getLocation(attributeName);
if(location == -1)
{
// TODO: fail silently?
ACGL::Utils::error() << "can't update VAO mappings: attribute " << attributeName << " not specified" << std::endl;
continue; // try to match as much as possible
}
if(mAttributes[i].location != location)
{
mAttributes[i].location = location;
fullUpdateNeeded = true;
}
}
// why the full update? setting the new location right when a change is detected will get problamatic
// if two attributes exchange there position...
if (fullUpdateNeeded)
{
enable();
// disable all attributes
GLint maxAttributes;
glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &maxAttributes );
for (GLint i = 0; i < maxAttributes; ++i)
glDisableVertexAttribArray( i );
// set all attributes:
for (uint32_t i = 0; i < mAttributes.size(); ++i)
{
setAttributePointer(mAttributes[i]);
}
disable();
}
}
private:
//! Sets the vertex attribute pointer for the current VAO according to the specified attribute data
//! Note: expects that this VAO is currently bound
......
......@@ -68,3 +68,133 @@ void FrameBufferObject::validate(void) const
else
Utils::error() << "FrameBufferObject validation failed: No color attachments."<< std::endl;
}
void FrameBufferObject::setAttachmentsByShaderProgram(ConstSharedShaderProgram _shaderProgram)
{
// TODO: deprecate
bool needsUpdate = false;
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
{
GLint fragDataLocation = _shaderProgram->getFragmentDataLocation(mColorAttachments[i].name);
if(fragDataLocation != -1 // does a fragment data location by that name exist in the ShaderProgram?
&& fragDataLocation != mColorAttachmentIndices[mColorAttachments[i].name]) // does it match the index of the color attachment?
{
mColorAttachmentIndices[mColorAttachments[i].name] = fragDataLocation;
needsUpdate = true;
}
}
if(needsUpdate)
{
bind();
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
{
if(mColorAttachments[i].texture)
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[mColorAttachments[i].name],
mColorAttachments[i].texture->getTarget(),
mColorAttachments[i].texture->getObjectName(),
0
);
if(mColorAttachments[i].renderBuffer)
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[mColorAttachments[i].name],
GL_RENDERBUFFER,
mColorAttachments[i].renderBuffer->getObjectName()
);
}
}
openGLRareError();
}
void FrameBufferObject::setAttachmentLocations(ConstSharedLocationMappings _locationMappings)
{
bool needsUpdate = false;
// First, erase all existing frag data location mappings that coincide with names specified in _locationMappings
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
{
int_t location = _locationMappings->getLocation(mColorAttachments[i].name);
if(location != -1) // is a mapping by that name specified?
{
// remove previous frag data location pointing to this color attachment
mFragDataLocationIndices.erase(i);
//ACGL::Utils::debug() << "Dropping attachment for " << mColorAttachments[i].name << " (index " << i << ")" << std::endl;
needsUpdate = true;
}
}
// Then, wire up the new mappings
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
{
int_t location = _locationMappings->getLocation(mColorAttachments[i].name);
//ACGL::Utils::debug() << "Color attachment " << mColorAttachments[i].name << " (index " << i << ") should be mapped to frag data location " << location;
//ACGL::Utils::debug() << ". Currently mapped to: " << mFragDataLocationIndices[location] << std::endl;
if(location != -1) // is a mapping by that name specified?
{
//ACGL::Utils::debug() << "Attaching frag data location " << location << " to color attachment " << i << std::endl;
mFragDataLocationIndices[location] = i;
}
}
if(needsUpdate)
{
updateDrawBuffers();
}
}
void FrameBufferObject::updateDrawBuffers()
{
// No fragment data mappings set up? -> Nothing to do
if(mFragDataLocationIndices.size() == 0)
{
return;
}
// The (temporary) buffer mapping table must be large enough to contain all mapped frag data locations
GLint maxDrawBuffers; glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); // TODO: clever caching?
GLsizei numBuffers = std::min(mFragDataLocationIndices.rbegin()->first + 1, maxDrawBuffers);
GLenum* buffers = new GLenum[numBuffers];
for(GLsizei i = 0; i < numBuffers; ++i)
{
// frag data mapping for this index exists?
if(mFragDataLocationIndices.count(i) > 0)
{
// map the frag data location to the given color attachment
buffers[i] = GL_COLOR_ATTACHMENT0 + mFragDataLocationIndices[i];
//ACGL::Utils::debug() << "mFragDataLocationIndices[" << i << "] = " << mFragDataLocationIndices[i] << std::endl;
}
else
{
buffers[i] = GL_NONE;
}
}
// TODO: remove debug output
ACGL::Utils::debug() << "Uploading mapping:";
for(int i = 0; i < numBuffers; ++i) {
//ACGL::Utils::debug() << " " << buffers[i];
}
ACGL::Utils::debug() << std::endl;
// upload the new mapping
bind();
glDrawBuffers(numBuffers, buffers);
delete[] buffers;
openGLRareError();
}
......@@ -16,8 +16,10 @@ using namespace ACGL::Base;
using namespace ACGL::Utils;
using namespace ACGL::OpenGL;
void RenderObject::updateMappings (void)
void RenderObject::updateMappings()
{
// TODO: reimplement
/*
for(VertexBufferObject::AttributeVec::size_type i = 0; i < mpVertexBufferObject->getAttributes().size(); ++i)
{
AttributeMapping mapping = {(int_t)i, (int_t)mpShaderProgramObject->getShaderProgram()->getAttributeLocation(mpVertexBufferObject->getAttributes()[i].name)};
......@@ -41,74 +43,64 @@ void RenderObject::updateMappings (void)
for(FrameBufferObject::AttachmentVec::size_type i = 0; i < mpFrameBufferObject->getColorAttachments().size(); ++i)
mpDrawBuffers[i] = GL_COLOR_ATTACHMENT0 + mpShaderProgramObject->getShaderProgram()->getFragmentDataLocation(mpFrameBufferObject->getColorAttachments()[i].name);
}
*/
// update the attribute locations of the VAO
// TODO: better move this to the controller
//mpVertexArrayObject->setAttributeLocationsByShaderProgram(mpShaderProgramObject->getShaderProgram());
// update the fragment data locations of the FBO
//mpFrameBufferObject->setAttachmentsByShaderProgram(mpShaderProgramObject->getShaderProgram());
openGLRareError();
}
void RenderObject::bindFrameBufferObject (void) const
void RenderObject::bindFrameBufferObject() const
{
if(mpFrameBufferObject)
{
mpFrameBufferObject->bind();
glDrawBuffers(mpFrameBufferObject->getColorAttachments().size(), mpDrawBuffers);
openGLRareError();
//glDrawBuffers(mpFrameBufferObject->getColorAttachments().size(), mpDrawBuffers);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
openGLRareError();
}
openGLRareError();
}
void RenderObject::useShaderProgramObject (void) const
void RenderObject::useShaderProgramObject() const
{
mpShaderProgramObject->use();
openGLRareError();
}
void RenderObject::enableVertexBufferObject (void) const
void RenderObject::enableVertexArrayObject() const
{
// TODO: deprecate
/*
if(mpVertexBufferObject->getElementArrayBuffer())
mpVertexBufferObject->getElementArrayBuffer()->bind();
int currentArrayBufferID = -1;
for(AttributeMappingVec::size_type i = 0; i < mAttributeMappings.size(); i++)
if(mpVertexArrayObject)
{
if(mAttributeMappings[i].attributeLocation != -1)
{
if(mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID != currentArrayBufferID)
{
mpVertexBufferObject->getArrayBuffers()[mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID]->bind();
currentArrayBufferID = mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID;
}
mpVertexBufferObject->setAttributePointer(mAttributeMappings[i].attributeID, mAttributeMappings[i].attributeLocation);
glEnableVertexAttribArray(mAttributeMappings[i].attributeLocation);
openGLRareError();
}
mpVertexArrayObject->enable();
}
*/
else
{
glBindVertexArray(0);
}
openGLRareError();
}
void RenderObject::disableVertexBufferObject (void) const
void RenderObject::disableVertexArrayObject() const
{
// TODO: deprecate
/*
int currentArrayBufferID = -1;
for(AttributeMappingVec::size_type i = 0; i < mAttributeMappings.size(); i++)
glBindVertexArray(0);
openGLRareError();
}
void RenderObject::useViewport() const
{
if(mpViewport)
{
if(mAttributeMappings[i].attributeLocation != -1)
{
if(mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID != currentArrayBufferID)
{
mpVertexBufferObject->getArrayBuffers()[mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID]->bind();
currentArrayBufferID = mpVertexBufferObject->getAttributes()[mAttributeMappings[i].attributeID].bufferID;
}
glDisableVertexAttribArray(mAttributeMappings[i].attributeLocation);
openGLRareError();
}
mpViewport->use();
}
*/
openGLRareError();
}
#endif
......@@ -5,13 +5,14 @@
#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
#include <ACGL/OpenGL/Objects/VertexArrayObject.hh>
#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
#include <ACGL/OpenGL/Tools.hh>
using namespace ACGL::OpenGL;
using namespace ACGL::Base;
using namespace ACGL::Utils;
bool ShaderProgram::link(void) const
bool ShaderProgram::link() const
{
glLinkProgram(mObjectName);
......@@ -49,8 +50,10 @@ bool ShaderProgram::link(void) const
return true;
}
void ShaderProgram::setAttributeLocationsByVAO( const SharedVertexArrayObject& _vao )
void ShaderProgram::setAttributeLocationsByVAO(ConstSharedVertexArrayObject _vao)
{
// TODO: deprecate