#ifndef UNIFORM_BLOCK_ARRAY_H#define UNIFORM_BLOCK_ARRAY_H//To use this file, you must include one of the glload headers before including this.#include <string.h>#include <vector>namespaceFramework{//This object can only be constructed after an OpenGL context has been created and initialized.template<typenameUniformBlockObject,intarrayCount>classUniformBlockArray{public:UniformBlockArray():m_storage(),m_blockOffset(0){intuniformBufferAlignSize=0;glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,&uniformBufferAlignSize);m_blockOffset=sizeof(UniformBlockObject);m_blockOffset+=uniformBufferAlignSize-(m_blockOffset%uniformBufferAlignSize);intsizeMaterialUniformBuffer=m_blockOffset*arrayCount;m_storage.resize(arrayCount*m_blockOffset,0);}intsize()const{returnarrayCount;}//The array offset should be multiplied by the array index to get the offset//for a particular element.intGetArrayOffset()const{returnm_blockOffset;}classBlockMemberReference{private:BlockMemberReference(UniformBlockArray&uboArray,intblockIndex):m_array(uboArray),m_blockIndex(blockIndex){}public:~BlockMemberReference(){}operatorUniformBlockObject()const{UniformBlockObjecttheObject;memcpy(&theObject,&m_array.m_storage[m_blockIndex*m_array.m_blockOffset],sizeof(UniformBlockObject));returntheObject;}BlockMemberReference&operator=(constUniformBlockObject&input){memcpy(&m_array.m_storage[m_blockIndex*m_array.m_blockOffset],&input,sizeof(UniformBlockObject));return*this;}private:UniformBlockArray&m_array;intm_blockIndex;friendclassUniformBlockArray;};BlockMemberReferenceoperator[](size_tindex){assert(index<arrayCount);returnBlockMemberReference(*this,index);}GLuintCreateBufferObject(){GLuintbufferObject;glGenBuffers(1,&bufferObject);glBindBuffer(GL_UNIFORM_BUFFER,bufferObject);glBufferData(GL_UNIFORM_BUFFER,m_storage.size(),&m_storage[0],GL_STATIC_DRAW);glBindBuffer(GL_UNIFORM_BUFFER,0);returnbufferObject;}private:std::vector<GLubyte>m_storage;intm_blockOffset;};}#endif //UNIFORM_BLOCK_ARRAY_H