Commit aa066185 authored by Robert Menzel's avatar Robert Menzel

FBO redone

parent 2c552974
......@@ -30,7 +30,7 @@
#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/ShaderProgram.hh>
#include <ACGL/OpenGL/Objects/LocationMappings.hh>
#include <vector>
......@@ -43,12 +43,6 @@ class FrameBufferObject
{
ACGL_NOT_COPYABLE(FrameBufferObject)
// =================================================================================================== \/
// ============================================================================================ STATIC \/
// =================================================================================================== \/
private:
static GLuint msBuffers[8];
// ==================================================================================================== \/
// ============================================================================================ STRUCTS \/
// ==================================================================================================== \/
......@@ -56,10 +50,10 @@ public:
//! An attachment can be a texture or a render buffer
struct Attachment
{
std::string name;
ConstSharedTexture texture;
ConstSharedRenderBuffer renderBuffer;
int_t fragDataLocation; // the frag data location that maps to this attachment
std::string name; // user defined name that matches the fragment shader out
ConstSharedTexture texture; // attached color texture, or:
ConstSharedRenderBuffer renderBuffer; // attached renderbuffer - only this or the texture should be set!
GLuint location; // the frag data location that maps to this attachment
};
// ===================================================================================================== \/
......@@ -74,10 +68,7 @@ public:
public:
FrameBufferObject(void)
: mObjectName(0),
mDrawBuffers(0),
mColorAttachments(),
mColorAttachmentIndices(),
mFragDataLocationIndices(),
mDepthAttachment()
{
glGenFramebuffers(1, &mObjectName);
......@@ -86,9 +77,10 @@ public:
ACGL::Utils::error() << "could not generate FrameBufferObject!" << std::endl;
return;
}
mDepthAttachment.name = "";
mDepthAttachment.texture = ConstSharedTexture();
mDepthAttachment.texture = ConstSharedTexture();
mDepthAttachment.renderBuffer = ConstSharedRenderBuffer();
mDepthAttachment.name = ""; // not useful here
mDepthAttachment.location = -1; // not useful here
}
virtual ~FrameBufferObject(void)
......@@ -140,56 +132,36 @@ public:
openGLRareError();
}*/
//! let OpenGL validate the completeness
bool isFrameBufferObjectComplete() const;
inline bool attachColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer)
/*
* Attach another RenderBuffer as a render target. If the name already exists the old target will get replaced.
*/
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 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;
return attachColorAttachment( (Attachment){_name, SharedTexture(), _renderBuffer, mColorAttachments.size()} );
}
inline bool attachColorTexture(const std::string _name, const ConstSharedTexture& _texture)
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())
{
Utils::error() << "Attaching of texture to the FBO failed" << std::endl;
return false;
}
Attachment attachment = {_name, _texture, SharedRenderBuffer()};
mColorAttachments.push_back(attachment);
mColorAttachmentIndices[_name] = mDrawBuffers;
mFragDataLocationIndices[mDrawBuffers] = mDrawBuffers;
mDrawBuffers++;
return true;
return attachColorAttachment( (Attachment){_name, _texture, SharedRenderBuffer(), mColorAttachments.size()} );
}
inline bool setColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer)
inline bool attachColorRenderBuffer(const std::string &_name, const ConstSharedRenderBuffer& _renderBuffer, GLuint _location )
{
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[_name], GL_RENDERBUFFER, _renderBuffer->getObjectName() );
return true;
return attachColorAttachment( (Attachment){_name, SharedTexture(), _renderBuffer, _location} );
}
inline bool setColorTexture(const std::string _name, const ConstSharedTexture& _texture)
inline bool attachColorTexture(const std::string &_name, const ConstSharedTexture& _texture, GLuint _location )
{
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[_name], _texture->getTarget(), _texture->getObjectName(), 0 );
return true;
return attachColorAttachment( (Attachment){_name, _texture, SharedRenderBuffer(), _location} );
}
bool attachColorAttachment( const Attachment &_attachment );
void remapAttachments();
inline bool setDepthRenderBuffer(const ConstSharedRenderBuffer& _renderBuffer)
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
......@@ -226,30 +198,20 @@ public:
// =========================================================================================== 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();
//! get a list of attachment locations and names that can be used to set up a ShaderProgram
SharedLocationMappings getAttachmentLocations();
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
protected:
GLuint mObjectName;
GLsizei mDrawBuffers;
AttachmentVec mColorAttachments;
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
Attachment mDepthAttachment; // depth and stencil are combined
GLuint mBufferMappings[8]; // maps from mColorAttachment.loction (shader outs) to FBO locations (order of mColorAttachments)
};
ACGL_SHARED_TYPEDEF(FrameBufferObject)
......
......@@ -99,39 +99,51 @@ public:
// ============================================================================================ WRAPPERS \/
// ===================================================================================================== \/
public:
inline GLint getUniformLocation (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
inline GLint getAttributeLocation (const std::string& _nameInShader) const { return glGetAttribLocation (mObjectName, _nameInShader.c_str()); }
inline void bindAttributeLocation (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation (mObjectName, _location, _nameInShader.c_str()); }
#if (ACGL_OPENGL_VERSION >= 30)
inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
#endif // OpenGL >= 3.0
//! use, or activate it for rendering, also needed to set uniforms:
inline void use(void) const { glUseProgram(mObjectName); }
//! attach a single shader, don't forget to relink!
inline void attachShader(const ConstSharedShader& _shader)
{
mShaders.push_back(_shader);
glAttachShader( mObjectName, _shader->getObjectName() );
}
//! link the program, has to be redone after changing input or output locations:
bool link (void) const;
// ===================================================================================================== \/
// ============================================================================================= METHODS \/
// =========================================================================================== LOCATIONS \/
// ===================================================================================================== \/
public:
// Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _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 );
//////////// uniform locations:
inline GLint getUniformLocation (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
//////////// attribute locations:
inline GLint getAttributeLocation (const std::string& _nameInShader) const { return glGetAttribLocation (mObjectName, _nameInShader.c_str()); }
inline void bindAttributeLocation (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation (mObjectName, _location, _nameInShader.c_str()); }
//! Sets the attribute locations of this ShaderProgram according to the mappings specified in
void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
//! Get all attribute names with there locations:
SharedLocationMappings getAttributeLocations();
//////////// fragdata locations:
#if (ACGL_OPENGL_VERSION >= 30)
inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
//! Sets the fragment data locations of this ShaderProgram according to the mappings specified in
void setFragmentDataLocations( ConstSharedLocationMappings _locationMappings );
//! Get all fragdata names with there locations:
SharedLocationMappings getFragmentDataLocations();
#endif // OpenGL >= 3.0
// Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _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 );
// ===================================================================================================== \/
// ============================================================================================ UNIFORMS \/
......
......@@ -8,21 +8,6 @@
using namespace ACGL;
using namespace ACGL::OpenGL;
/*
* We can't use the constants GL_COLOR_ATTACHMENT1 to GL_COLOR_ATTACHMENT7 here
* because OpenGL ES does not know these yet.
*/
GLuint FrameBufferObject::msBuffers[8] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT0+1,
GL_COLOR_ATTACHMENT0+2,
GL_COLOR_ATTACHMENT0+3,
GL_COLOR_ATTACHMENT0+4,
GL_COLOR_ATTACHMENT0+5,
GL_COLOR_ATTACHMENT0+6,
GL_COLOR_ATTACHMENT0+7};
int_t FrameBufferObject::getColorAttachmentIndexByName(const std::string& _name) const
{
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
......@@ -96,132 +81,103 @@ void FrameBufferObject::validate(void) const
Utils::error() << "FrameBufferObject validation failed: No color attachments."<< std::endl;
}
void FrameBufferObject::setAttachmentsByShaderProgram(ConstSharedShaderProgram _shaderProgram)
bool FrameBufferObject::attachColorAttachment( const Attachment &_attachment )
{
// TODO: deprecate
int realLocation = -1;
bool needsUpdate = false;
for (unsigned int i = 0; i < mColorAttachments.size(); ++i) {
if (mColorAttachments[i].name == _attachment.name) {
// replace this attachment
mColorAttachments[i] = _attachment;
realLocation = i;
}
}
if (realLocation == -1) {
// it's a new attachment
realLocation = mColorAttachments.size();
mColorAttachments.push_back(_attachment);
}
for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
// attach it to the OpenGL object:
bind();
openGLCriticalErrorOccured();
if (_attachment.renderBuffer) {
// it's a renderBuffer
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + realLocation, GL_RENDERBUFFER, _attachment.renderBuffer->getObjectName() );
} else {
// it's a texture
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + realLocation, _attachment.texture->getTarget(), _attachment.texture->getObjectName(), 0 );
Utils::debug() << "glFramebufferTexture2D( " << _attachment.name << " to " << realLocation <<" )" << std::endl;
}
if (openGLCommonErrorOccured())
{
GLint fragDataLocation = _shaderProgram->getFragmentDataLocation(mColorAttachments[i].name);
Utils::error() << "Attaching of render target to the FBO failed" << std::endl;
return false;
}
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;
remapAttachments();
return true;
}
needsUpdate = true;
}
}
void FrameBufferObject::remapAttachments()
{
// max color attachments: 8, TODO
const int maxColorBuffers = 8;
GLenum bufferMappings[maxColorBuffers];
unsigned int attachments = std::min( maxColorBuffers, (int) mColorAttachments.size() );
if(needsUpdate)
{
bind();
for (unsigned int i = 0; i < maxColorBuffers; ++i) {
bufferMappings[i] = GL_NONE;
}
for (unsigned int i = 0; i < attachments; ++i) {
bufferMappings[ mColorAttachments[i].location ] = GL_COLOR_ATTACHMENT0 + i;
}
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()
);
// debug:
Utils::message() << "remapAttachments: " << std::endl;
for (unsigned int i = 0; i < maxColorBuffers; ++i) {
if (bufferMappings[i] == GL_NONE) {
Utils::debug() << "bufferMappings["<<i<<"] GL_NONE" << std::endl;
} else {
Utils::debug() << "bufferMappings["<<i<<"] "<< bufferMappings[i]-GL_COLOR_ATTACHMENT0 << std::endl;
}
}
// end debug
openGLRareError();
bind(); // glDrawBuffers will get part of the FBO state!
glDrawBuffers( maxColorBuffers, bufferMappings );
}
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?
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;
mColorAttachments[i].location = location;
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();
}
if(needsUpdate) remapAttachments();
}
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);
SharedLocationMappings FrameBufferObject::getAttachmentLocations()
{
SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
GLenum* buffers = new GLenum[numBuffers];
for(GLsizei i = 0; i < numBuffers; ++i)
for (AttachmentVec::size_type i = 0; i < mColorAttachments.size(); 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;
}
locationMap->setLocation( mColorAttachments[i].name, mColorAttachments[i].location );
//ACGL::Utils::debug() << "locationMap->setLocation( "<<mColorAttachments[i].name<<", "<<mColorAttachments[i].location<<" );"<<std::endl;
}
// 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();
return locationMap;
}
......@@ -94,10 +94,13 @@ void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locati
// find out whether a fragment data location with a matching name exists in this shader
GLint fragmentDataLocation = getFragmentDataLocation((*it).first);
//ACGL::Utils::debug() << "test ("<<(*it).first<<", "<<(*it).second<<"); loc:"<<fragmentDataLocation<<std::endl;
if ( fragmentDataLocation != -1 // fragment data location with that name exists?
&& ((GLuint) fragmentDataLocation) != (*it).second) // fragment data location with that name not already bound correctly?
{
bindFragmentDataLocation((*it).first, (*it).second);
ACGL::Utils::debug() << "bindFragmentDataLocation("<<(*it).first<<", "<<(*it).second<<");"<<std::endl;
needsRelink = true;
}
}
......@@ -110,6 +113,47 @@ void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locati
}
}
SharedLocationMappings ShaderProgram::getAttributeLocations()
{
SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
// query the number of _active_ attributes:
GLint attributeCount;
glGetProgramiv( mObjectName, GL_ACTIVE_ATTRIBUTES, &attributeCount );
if (attributeCount == 0) return locationMap;
// reserve a string long enought for the longest name:
GLint longestAttributeName;
glGetProgramiv( mObjectName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &longestAttributeName );
char *name = new char[longestAttributeName+1];
// get the name and location of each active attribute:
for (int i = 0; i < attributeCount; ++i) {
GLenum type;
GLint size;
GLsizei length;
glGetActiveAttrib( mObjectName, i, longestAttributeName, &length, &size, &type, name );
name[ length+1 ] = 0; // null terminate
GLint attribLocation = glGetAttribLocation( mObjectName, name );
//ACGL::Utils::debug() << "found attrib " << name << " at " << attribLocation << std::endl;
locationMap->setLocation( std::string(name), (GLuint) attribLocation );
}
delete name;
return locationMap;
}
SharedLocationMappings ShaderProgram::getFragmentDataLocations()
{
SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
ACGL::Utils::error() << " ShaderProgram::getFragmentDataLocations is not implemented -> missing OpenGL API" << std::endl;
return locationMap;
}
/*
......
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