Commit 08cb0ef2 authored by Robert Menzel's avatar Robert Menzel

Added UniformBufferObjects

parent 47e09f81
......@@ -16,6 +16,7 @@
#include <ACGL/OpenGL/Objects/ElementArrayBuffer.hh>
#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
#include <ACGL/OpenGL/Objects/RenderBuffer.hh>
#include <ACGL/OpenGL/Objects/UniformBuffer.hh>
#include <ACGL/OpenGL/Objects/RenderObject.hh>
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
......
......@@ -150,6 +150,7 @@ public:
inline GLint getAccessFlags() { return (GLint) getParameter ( GL_BUFFER_ACCESS_FLAGS ); }
inline GLboolean isMapped() { return (GLboolean) getParameter ( GL_BUFFER_MAPPED ); }
//! the size is in bytes
inline GLint64 getSize() { return mSize; }
//! Bind this buffer
......@@ -233,8 +234,29 @@ public:
flushMappedRange( mTarget, _offset, _length );
}
// TODO: bindBufferRange
// TODO: bindBufferBase
//! valid targets are only GL_TRANSFORM_FEEDBACK_BUFFER and GL_UNIFORM_BUFFER
inline void bindBufferRange( GLenum _target, GLuint _index, GLintptr _offset, GLsizeiptr _size ) {
glBindBufferRange( _target, _index, mBuffer->mObjectName, _offset, _size );
}
//! maps a subset of the buffer defined by _offset and _size
//! valid targets are only GL_TRANSFORM_FEEDBACK_BUFFER and GL_UNIFORM_BUFFER
inline void bindBufferRange( GLuint _index, GLintptr _offset, GLsizeiptr _size ) {
glBindBufferRange( mTarget, _index, mBuffer->mObjectName, _offset, _size );
}
//! maps the full buffer to the given index (binding point)
//! valid targets are only GL_TRANSFORM_FEEDBACK_BUFFER and GL_UNIFORM_BUFFER
inline void bindBufferBase( GLenum _target, GLuint _index ) {
glBindBufferBase( _target, _index, mBuffer->mObjectName );
}
//! maps the full buffer to the given index (binding point)
//! valid targets are only GL_TRANSFORM_FEEDBACK_BUFFER and GL_UNIFORM_BUFFER
inline void bindBufferBase( GLuint _index ) {
glBindBufferBase( mTarget, _index, mBuffer->mObjectName );
}
#endif // OpenGL >= 3.0
//! Maps the whole buffer, if using GL 3+, better use mapRange!
......
......@@ -110,12 +110,29 @@ public:
// =========================================================================================== LOCATIONS \/
// ===================================================================================================== \/
//////////// uniform locations:
inline GLint getUniformLocation (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
//////////// uniform (block) locations:
inline GLint getUniformLocation (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
#if (ACGL_OPENGL_VERSION >= 31)
//! if the block name does not exist, GL_INVALID_INDEX will get returned
inline GLuint getUniformBlockIndex (const std::string& _nameInShader) { return glGetUniformBlockIndex(mObjectName, _nameInShader.c_str()); }
inline void setUniformBlockBinding( GLuint _blockIndex, GLuint _bindingPoint ) { glUniformBlockBinding( mObjectName, _blockIndex, _bindingPoint ); }
inline void setUniformBlockBinding( const std::string& _blockName, GLuint _bindingPoint ) { glUniformBlockBinding( mObjectName, getUniformBlockIndex(_blockName), _bindingPoint ); }
//! returns a mapping from the uniforms in a given block to the offset within the block
SharedLocationMappings getUniformOffsetsOfBlock( const std::string &_blockName ) { return getUniformOffsetsOfBlock(getUniformBlockIndex(_blockName)); }
SharedLocationMappings getUniformOffsetsOfBlock( GLuint _blockIndex );
//! returns the size in bytes of the uniform block, can be used to allocate the right amount of memory
GLsizeiptr getUniformBlockSize( const std::string &_blockName ) { return getUniformBlockSize(getUniformBlockIndex(_blockName)); }
GLsizeiptr getUniformBlockSize( GLuint _blockIndex );
#endif // OpenGL >= 3.1
//////////// 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()); }
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 );
......@@ -124,6 +141,7 @@ public:
//////////// fragdata locations:
#if (ACGL_OPENGL_VERSION >= 30)
//! if the location does not exist, -1 will get returned
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()); }
......
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012, Computer Graphics Group RWTH Aachen University //
// All rights reserved. //
////////////////////////////////////////////////////////////////////////////////
#ifndef ACGL_OPENGL_OBJECTS_UNIFORM_BUFFER_HH
#define ACGL_OPENGL_OBJECTS_UNIFORM_BUFFER_HH
#include <ACGL/ACGL.hh>
#include <ACGL/Base/Macros.hh>
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
#include <ACGL/OpenGL/Objects/Buffer.hh>
#include <ACGL/OpenGL/Objects/LocationMappings.hh>
#include <ACGL/Math/Math.hh>
namespace ACGL{
namespace OpenGL{
/**
* An OpenGL Uniform Buffer Object that can be used to share blocks of uniforms between multiple ShaderPrograms.
*/
#if (ACGL_OPENGL_VERSION >= 31)
class UniformBuffer : public Buffer
{
// ========================================================================================================= \/
// ============================================================================================ CONSTRUCTORS \/
// ========================================================================================================= \/
public:
UniformBuffer()
: Buffer(GL_UNIFORM_BUFFER)
{}
UniformBuffer( SharedBufferObject _pBuffer )
: Buffer(_pBuffer, GL_UNIFORM_BUFFER)
{}
// ==================================================================================================== \/
// ============================================================================================ GETTERS \/
// ==================================================================================================== \/
public:
GLint getUniformOffset (const std::string& _nameInShader) const {
if (!uniformNameToOffsetMap) return -1;
return uniformNameToOffsetMap->getLocation(_nameInShader);
}
void setUniformOffsets (SharedLocationMappings _uniformNameToOffsetMap) { uniformNameToOffsetMap = _uniformNameToOffsetMap; }
// ==================================================================================================== \/
// ============================================================================================ SETTERS \/
// ==================================================================================================== \/
public:
//! reserve a number of bytes on the GPU for uniforms
inline void reserveMemory(GLsizeiptr _size){ setData( _size, NULL, GL_STREAM_DRAW ); }
// for scalar types:
inline void setUniform (const std::string &_nameInShader, GLfloat _v) { setUniformScalar<GLfloat> (_nameInShader, _v); }
inline void setUniform (const std::string &_nameInShader, GLint _v) { setUniformScalar<GLint> (_nameInShader, _v); }
inline void setUniform (const std::string &_nameInShader, GLuint _v) { setUniformScalar<GLuint> (_nameInShader, _v); }
inline void setUniform (const std::string &_nameInShader, GLboolean _v) { setUniformScalar<GLboolean>(_nameInShader, _v); }
inline void setUniform (const std::string &_nameInShader, GLdouble _v) { setUniformScalar<GLdouble> (_nameInShader, _v); }
// for GLM types:
template <typename T>
void setUniform (const std::string &_nameInShader, T _v) {
GLint offset = getUniformOffset( _nameInShader );
if (offset == -1) {
ACGL::Utils::error() << "UniformBuffer does not know uniform " << _nameInShader << std::endl;
return;
}
setSubData( offset, sizeof(T), glm::value_ptr(_v) );
}
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
private:
// for scalar types:
template <typename T>
void setUniformScalar (const std::string &_nameInShader, T _v) {
GLint offset = getUniformOffset( _nameInShader );
if (offset == -1) {
ACGL::Utils::error() << "UniformBuffer does not know uniform " << _nameInShader << std::endl;
return;
}
setSubData( offset, sizeof(T), &_v );
}
SharedLocationMappings uniformNameToOffsetMap;
};
ACGL_SMARTPOINTER_TYPEDEFS(UniformBuffer)
#endif // OpenGL >= 3.1
} // OpenGL
} // ACGL
#endif // ACGL_OPENGL_OBJECTS_UNIFORM_BUFFER_HH
......@@ -133,14 +133,14 @@ SharedLocationMappings ShaderProgram::getAttributeLocations()
GLint size;
GLsizei length;
glGetActiveAttrib( mObjectName, i, longestAttributeName, &length, &size, &type, name );
name[ length+1 ] = 0; // null terminate
name[ length+1 ] = 0; // null terminate string
GLint attribLocation = glGetAttribLocation( mObjectName, name );
locationMap->setLocation( std::string(name), (GLuint) attribLocation );
}
delete name;
delete[] name;
return locationMap;
}
......@@ -153,3 +153,53 @@ SharedLocationMappings ShaderProgram::getFragmentDataLocations()
return locationMap;
}
SharedLocationMappings ShaderProgram::getUniformOffsetsOfBlock( GLuint _blockIndex )
{
SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
if (_blockIndex == GL_INVALID_INDEX) return locationMap; // block does not exist
// query the number of _active_ uniforms:
GLint uniformCount;
glGetProgramiv( mObjectName, GL_ACTIVE_UNIFORMS, &uniformCount );
if (uniformCount == 0) return locationMap;
// reserve a string long enought for the longest name:
GLint longestUniformName;
glGetProgramiv( mObjectName, GL_ACTIVE_UNIFORM_MAX_LENGTH, &longestUniformName );
char *name = new char[longestUniformName+1];
// get the name and location of each active attribute:
for (int i = 0; i < uniformCount; ++i) {
GLsizei length;
glGetActiveUniformName( mObjectName, i, longestUniformName, &length, name );
name[ length+1 ] = 0; // null terminate string
GLuint idx = i;
GLint uniformBlockIndex;
glGetActiveUniformsiv( mObjectName, 1, &idx, GL_UNIFORM_BLOCK_INDEX, &uniformBlockIndex );
if (uniformBlockIndex != -1) {
if ((GLuint)uniformBlockIndex == _blockIndex) {
GLint offset;
glGetActiveUniformsiv( mObjectName, 1, &idx, GL_UNIFORM_OFFSET, &offset );
//ACGL::Utils::message() << "uniform " << i << " is " << name << " block: " << uniformBlockIndex << " offset: " << offset << std::endl;
locationMap->setLocation( std::string(name), (GLuint) offset );
}
}
}
delete[] name;
return locationMap;
}
GLsizeiptr ShaderProgram::getUniformBlockSize( GLuint _blockIndex )
{
if (_blockIndex == GL_INVALID_INDEX) return 0; // block does not exist
GLint uniformBlockSize;
glGetActiveUniformBlockiv( mObjectName, _blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uniformBlockSize);
return (GLsizeiptr) uniformBlockSize;
}
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University //
// All rights reserved. //
////////////////////////////////////////////////////////////////////////////////
#include <ACGL/OpenGL/Objects/UniformBuffer.hh>
using namespace ACGL;
using namespace ACGL::OpenGL;
#if (ACGL_OPENGL_VERSION >= 31)
#endif // OpenGL 3.1
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