Commits

Jason McKesson committed 2892f5c

glmesh: Vertex Format changes. Some Boost usage now.

Comments (0)

Files changed (7)

 \page pg_changelist Changelist
 
 Changes from 0.4.4:
+\li @ref module_glmesh "GL Mesh"'s VertexFormat::Enable class now can use ARB_vertex_attrib_binding.
 \li Now includes glLoadGen.
 \li Modified how GL Load works, using glLoadGen's code generation system.
 \li C++ GL Load now doesn't need to prefix its enums with GL_.

glmesh/glmesh.lua

 	kind "StaticLib"
 	language "c++"
 	includedirs {"include", "source",
-		"../glload/include", "../glutil/include", "../glm"}
+		"../glload/include", "../glutil/include", "../glm", "../boost"}
 	targetdir "lib"
 
 	files {

glmesh/include/glmesh/BoostDraw.h

+
+#ifndef GLSDK_MESH_DRAW_WITH_BOOST_H
+#define GLSDK_MESH_DRAW_WITH_BOOST_H
+
+#include "Draw.h"
+#include "VertexFormat.h"
+
+namespace glmesh
+{
+}
+
+
+
+#endif //GLSDK_MESH_DRAW_WITH_BOOST_H

glmesh/include/glmesh/Draw.h

 
-#ifndef DRAW_MESH_H
-#define DRAW_MESH_H
+#ifndef GLSDK_MESH_DRAW_H
+#define GLSDK_MESH_DRAW_H
 
 /**
 \file
 
 	///@}
 }
-#endif //DRAW_MESH_H
+#endif //GLSDK_MESH_DRAW_H

glmesh/include/glmesh/StreamBuffer.h

 
-#ifndef STREAM_BUFFER_MESH_H
-#define STREAM_BUFFER_MESH_H
+#ifndef GLSDK_MESH_STREAM_BUFFER_H
+#define GLSDK_MESH_STREAM_BUFFER_H
 
 /**
 \file
 	///@}
 }
 
-#endif //STREAM_BUFFER_MESH_H
+#endif //GLSDK_MESH_STREAM_BUFFER_H

glmesh/include/glmesh/VertexFormat.h

 
-#ifndef VERTEX_FORMAT_MESH_H
-#define VERTEX_FORMAT_MESH_H
+#ifndef GLSDK_MESH_VERTEX_FORMAT_H
+#define GLSDK_MESH_VERTEX_FORMAT_H
 
 /**
 \file
 		}
 	};
 
+	///Thrown if VertexFormat is given two AttribDesc objects that use the same attribute index.
 	class AttributeIndexMultipleRefException : public VertexFormatException
 	{
 	public:
 	other. The attributes always have 4 byte alignment, as there are some hardware that
 	really doesn't like misaligned data. Double-precision attributes have 8-byte alignment.
 
-	The byte offset of each attribute from the beginning of the vertex can be queried.
+	The byte offset of each attribute from the beginning of the vertex can be queried. This is
+	useful if all of the attributes come from the same buffer object's source.
 
 	Note that the order of the attribute sequence is the same as the order of the AttributeList.
 	This means that the order is \em not the order of the attribute indices. This is the order
 		/**
 		\brief Creates a VertexFormat from a sequence of AttribDesc objects.
 
-		The order fo the sequence of attributes will match the order of \a attribs.
+		The order of the sequence of attributes will match the order of \a attribs.
 		
-		\throw ddd If any of the \a attribs refer to the same attribute index as any of the others.
+		\throw AttributeIndexMultipleRefException If any of the \a attribs refer to the same attribute index as any of the others.
 		**/
 		VertexFormat(const AttributeList &attribs);
 
 		size_t GetAttribByteOffset(size_t attribIx) const;
 
 		/**
+		\brief Binds the VertexFormat to the context.
+
+		This function assumes that a valid VAO is bound (if one is needed), as well as GL_ARRAY_BUFFER.
+
+		The following OpenGL state is touched by this function:
+
+		\li The enable state of all of the attributes in the format will be set to enabled.
+		\li For each such attribute location, glVertexAttrib*Pointer will be called.
+
+		This function assumes that all vertex attributes come from the buffer object currently bound
+		to GL_ARRAY_BUFFER. Therefore, you can only use it with a single buffer object.
+
+		\param baseOffset The byte offset from the start of the buffer object to where the vertex data is.
+		**/
+		void BindAttributes(size_t baseOffset) const;
+
+		/**
+		\brief Binds the VertexFormat using ARB_vertex_attrib_format.
+
+		This function assumes that a valid VAO is bound (if one is needed).
+
+		The following OpenGL state is touched by this function:
+
+		\li The enable state of all of the attributes in the format will be set to enabled.
+		\li For each such attribute location, glVertexAttrib*Format will be called.
+
+		This function uses the offsets computed by GetAttribByteOffset, so it assumes that all vertex
+		attributes come from the buffer object currently bound to GL_ARRAY_BUFFER. Therefore, you
+		can only use it with a single buffer object.
+		**/
+		void BindAttribFormat() const;
+
+		/**
+		\brief Disables the attributes.
+
+		The following OpenGL state is touched by this function:
+
+		\li The enable state of all of the attributes in the format will be set to disabled.
+		**/
+		void DisableAttributes() const;
+
+		/**
 		\ingroup module_glmesh_draw
-		\brief RAII-style class for binding a VertexFormat to the OpenGL context. The destructor unbinds it.
+		\brief RAII-style class for binding a VertexFormat to the OpenGL context.
+		
+		The constructors of this class call BindAttributes or BindAttribFormat, as appropriate. The destructor
+		calls DisableAttributes.
+		
+		This class can use the ARB_vertex_attrib_binding functionality instead of glVertexAttribPointer. If it does,
+		it only changes the vertex format state, not the buffer binding state. That is, it will call
+		glEnable/DisableVertexAttrbiArray and glVertexAttribFormat, but not glVertexAttribBinding,
+		glBindVertexBuffer, or glVertexBindingDivisor.
 
-		This class assumes that a valid VAO is bound (if one is needed). It also assumes that
-		all vertex data comes from a single buffer object which has also been bound to GL_ARRAY_BUFFER.
+		Note that all of the attributes will still have the same stride, and the offsets will be computed
+		as though it all comes from a single buffer. You can use multiple separate VertexFormat objects,
+		if you want to define multiple different formats.
+		
+		If you are not using ARB_vertex_attrib_binding, then this class assumes that
+		all vertex data comes from the buffer currently bound to GL_ARRAY_BUFFER.
 
 		The following OpenGL state is touched by constructing this object:
 
-		\li For each attribute in the given VertexFormat, that attributes state will be changed. After this
-		object is destroyed, all of the attributes used by this VertexFormat will be disabled.
+		\li The enable/disable state of the attributes in the format.
+		\li If you are using ARB_vertex_attrib_binding, then the state set by glVertexAttrib*Format.
+		\li If not using ARB_vertex_attrib_binding, then the state set by glVertexAttrib*Pointer.
 
 		After creating one of these, you can use \c glDraw* functions to render from the previously
 		bound buffer object, using the VertexFormat given.
 		public:
 			/**
 			\brief Binds the vertex format to the OpenGL context, given a byte offset to the first vertex.
-			
-			\param fmt The format to bind to the context. Taken by reference; do not destroy
-			this before this object is destroyed.
-			\param baseOffset The byte offset from the beginning of the buffer to the first piece of
-			vertex data.
+
+			Calls VertexFormat::BindAttributes on \a fmt.
 			**/
 			Enable(const VertexFormat &fmt, size_t baseOffset);
 
+			/**
+			\brief Binds the vertex format to the OpenGL context, using ARB_vertex_attrib_binding.
+
+			Calls VertexFormat::BindAttribFormat on \a fmt.
+			**/
+			Enable(const VertexFormat &fmt);
+
 			///Unbinds the vertex format from the OpenGL context.
 			~Enable();
 
 }
 
 
-#endif //VERTEX_FORMAT_MESH_H
+#endif //GLSDK_MESH_VERTEX_FORMAT_H

glmesh/source/VertexFormat.cpp

 #include <glload/gl_all.hpp>
 #include <glload/gll.hpp>
 #include "glmesh/VertexFormat.h"
+#include <boost/foreach.hpp>
+#include <boost/static_assert.hpp>
 
 #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
 
 			4,
 			4,
 		};
+
+		BOOST_STATIC_ASSERT(NUM_VERTEX_DATA_TYPES == ARRAY_COUNT(g_byteSizesVertexTypes));
 	}
 
 	AttributeDataInvalidException::AttributeDataInvalidException( int numComponentsGiven )
 			gl::INT,
 			gl::UNSIGNED_INT,
 		};
+
+		BOOST_STATIC_ASSERT(NUM_VERTEX_DATA_TYPES == ARRAY_COUNT(t_vertexUploadType));
+	}
+
+	void VertexFormat::BindAttributes( size_t baseOffset ) const
+	{
+		const size_t numAttribs = GetNumAttribs();
+		for(size_t attribIx = 0; attribIx < numAttribs; ++attribIx)
+		{
+			const AttribDesc &attribute = GetAttribDesc(attribIx);
+			size_t offset = GetAttribByteOffset(attribIx);
+			const GLuint attributeIndex = attribute.GetAttribIndex();
+
+			gl::EnableVertexAttribArray(attributeIndex);
+			GLenum type = t_vertexUploadType[attribute.GetVertexDataType()];
+			GLint numComponents = static_cast<GLint>(attribute.GetNumComponents());
+			switch(attribute.GetAttribDataType())
+			{
+			case ADT_FLOAT:
+				gl::VertexAttribPointer(attributeIndex, numComponents, type, gl::FALSE_,
+					GetVertexByteSize(), reinterpret_cast<void*>(baseOffset + offset));
+				break;
+			case ADT_NORM_FLOAT:
+				gl::VertexAttribPointer(attributeIndex, numComponents, type, gl::TRUE_,
+					GetVertexByteSize(), reinterpret_cast<void*>(baseOffset + offset));
+				break;
+			case ADT_INTEGER:
+				gl::VertexAttribIPointer(attributeIndex, numComponents, type,
+					GetVertexByteSize(), reinterpret_cast<void*>(baseOffset + offset));
+				break;
+			case ADT_DOUBLE:
+				gl::VertexAttribLPointer(attributeIndex, numComponents, type,
+					GetVertexByteSize(), reinterpret_cast<void*>(baseOffset + offset));
+				break;
+			}
+		}
+	}
+
+	void VertexFormat::BindAttribFormat( ) const
+	{
+		const size_t numAttribs = GetNumAttribs();
+		for(size_t attribIx = 0; attribIx < numAttribs; ++attribIx)
+		{
+			const AttribDesc &attribute = GetAttribDesc(attribIx);
+			size_t offset = GetAttribByteOffset(attribIx);
+			const GLuint attributeIndex = attribute.GetAttribIndex();
+
+			gl::EnableVertexAttribArray(attributeIndex);
+			GLenum type = t_vertexUploadType[attribute.GetVertexDataType()];
+			GLint numComponents = static_cast<GLint>(attribute.GetNumComponents());
+
+			switch(attribute.GetAttribDataType())
+			{
+			case ADT_FLOAT:
+				gl::VertexAttribFormat(attributeIndex, numComponents, type, gl::FALSE_, offset);
+				break;
+			case ADT_NORM_FLOAT:
+				gl::VertexAttribFormat(attributeIndex, numComponents, type, gl::TRUE_, offset);
+				break;
+			case ADT_INTEGER:
+				gl::VertexAttribIFormat(attributeIndex, numComponents, type, offset);
+				break;
+			case ADT_DOUBLE:
+				gl::VertexAttribLFormat(attributeIndex, numComponents, type, offset);
+				break;
+			}
+		}
+	}
+
+	void VertexFormat::DisableAttributes() const
+	{
+		BOOST_FOREACH(const AttribDesc &attribute, m_attribs)
+		{
+			gl::DisableVertexAttribArray(attribute.GetAttribIndex());
+		}
 	}
 
 	VertexFormat::Enable::Enable( const VertexFormat &fmt, size_t baseOffset )
 		: m_fmt(fmt)
 	{
-		const size_t numAttribs = fmt.GetNumAttribs();
-		for(size_t attribIx = 0; attribIx < numAttribs; ++attribIx)
-		{
-			const AttribDesc &attribute = fmt.GetAttribDesc(attribIx);
-			size_t offset = fmt.GetAttribByteOffset(attribIx);
+		m_fmt.BindAttributes(baseOffset);
+	}
 
-			gl::EnableVertexAttribArray(attribute.GetAttribIndex());
-			GLenum type = t_vertexUploadType[attribute.GetVertexDataType()];
-			GLint numComponents = static_cast<GLint>(attribute.GetNumComponents());
-			switch(attribute.GetAttribDataType())
-			{
-			case ADT_FLOAT:
-				gl::VertexAttribPointer(attribute.GetAttribIndex(),
-					numComponents, type, gl::FALSE_, fmt.GetVertexByteSize(),
-					reinterpret_cast<void*>(baseOffset + offset));
-				break;
-			case ADT_NORM_FLOAT:
-				gl::VertexAttribPointer(attribute.GetAttribIndex(),
-					numComponents, type, gl::TRUE_, fmt.GetVertexByteSize(),
-					reinterpret_cast<void*>(baseOffset + offset));
-				break;
-			case ADT_INTEGER:
-				gl::VertexAttribIPointer(attribute.GetAttribIndex(),
-					numComponents, type, fmt.GetVertexByteSize(),
-					reinterpret_cast<void*>(baseOffset + offset));
-				break;
-			case ADT_DOUBLE:
-				gl::VertexAttribLPointer(attribute.GetAttribIndex(),
-					numComponents, type, fmt.GetVertexByteSize(),
-					reinterpret_cast<void*>(baseOffset + offset));
-				break;
-			}
-		}
+	VertexFormat::Enable::Enable( const VertexFormat &fmt )
+		: m_fmt(fmt)
+	{
+		m_fmt.BindAttribFormat();
 	}
 
 	VertexFormat::Enable::~Enable()
 	{
-		const size_t numAttribs = m_fmt.GetNumAttribs();
-		for(size_t attribIx = 0; attribIx < numAttribs; ++attribIx)
-		{
-			const AttribDesc &attribute = m_fmt.GetAttribDesc(attribIx);
-
-			gl::DisableVertexAttribArray(attribute.GetAttribIndex());
-		}
+		m_fmt.DisableAttributes();
 	}
 }