Vertex Declarations in OpenGL and DirectX ?
Hi,
What is the OpenGL echivalent for DirectX9 vertex declarations ?
I know that OpenGL can use vertex arrays that are echivalent for vertexbuffers.
But how to set vertex declarations, and can it use multiple streams (vertex arrays) ?
I want to know this for use with CG effects or vertex programs available for OpenGL.
Can anyone give a small code example (not necessarly functional, just curios about the functions used).
I am also interested in a platform independent approach to meshes and effects. Can vertex shaders and vertex declarations be wraped in some engine classes to use with both OpenGL and DirectX effects (eventualy CG) ?
Thanks
Moved to OpenGL
For the first part of your question you're more likely to get a better answer from the OpenGL experts - they're the guys who know the API best [wink]
AS for an API/platform independent method, yes it's probably possible - but you can't really take it any further until you know what form both API's can use (or require). From there you can either decide whether you want to take a subset approach (basic functionality that both API's can handle) or some higher-level approach that involves work-arounds/emulation for parts of the respective API's that don't natively handle what you want. For example, if you really want streams, but OpenGL can't do that you could (presumably) emulate it by creating your own Input Assembler - not necessarily efficient, but it'd probably work.
hth
Jack
For the first part of your question you're more likely to get a better answer from the OpenGL experts - they're the guys who know the API best [wink]
AS for an API/platform independent method, yes it's probably possible - but you can't really take it any further until you know what form both API's can use (or require). From there you can either decide whether you want to take a subset approach (basic functionality that both API's can handle) or some higher-level approach that involves work-arounds/emulation for parts of the respective API's that don't natively handle what you want. For example, if you really want streams, but OpenGL can't do that you could (presumably) emulate it by creating your own Input Assembler - not necessarily efficient, but it'd probably work.
hth
Jack
JollyJeffers,
i can't follow your explanation; so, plesae tell me, what do you mean exactly by the term "subset approach" ?
(do you mean splitting up the rendering-work into more/simple subsets by switching only the vertex-dec.format ?)
i can't follow your explanation; so, plesae tell me, what do you mean exactly by the term "subset approach" ?
(do you mean splitting up the rendering-work into more/simple subsets by switching only the vertex-dec.format ?)
about the vertex declaration in OpenGL, and multiple streams prepared for an effect, if anyone knows... please post some tips
What it comes down to in OpenGL is that you get to define vertex declarations yourself, and then you get to write the rendering backend code that translates a vertex declaration into BindBuffer and Pointer calls.
It's fairly simple to do. You define an array of structures that have all of the information about the vertex declaration -- what its usage is, what type it is, offset and stream index, etc. Then you loop through that array, calling BindBuffer and pointer as necessary.
I basically have a header that defines stuff for a declaration:
And then the function to parse this into OpenGL goes like this:
(Note: This appears to be an older version of my source. The newer version has some modifications that allow arbitrary VertexElementTypes, which is useful for shader stuff.)
It's fairly simple to do. You define an array of structures that have all of the information about the vertex declaration -- what its usage is, what type it is, offset and stream index, etc. Then you loop through that array, calling BindBuffer and pointer as necessary.
I basically have a header that defines stuff for a declaration:
#ifndef _GEOMETRY_H#define _GEOMETRY_H#include "../HoverEngine.h"#include "RendererTypes.h"#include "VertexBuffer.h"#include "IndexBuffer.h"#include <vector>//type of element, i.e. what it specifiesenum VertexElementType{ VET_XYZ, VET_NORMAL, VET_DIFFUSE, VET_SPECULAR, VET_TEXCOORD,};//'format' of element, basically the data type//it's recommended that you avoid the INT64 types, as well as long doubleenum VertexElementFormat{ VEF_SIGNED_BYTE, VEF_UNSIGNED_BYTE, VEF_SIGNED_SHORT, VEF_UNSIGNED_SHORT, VEF_UNSIGNED_INT, VEF_SIGNED_INT, VEF_UNSIGNED_INT64, VEF_SIGNED_INT64, VEF_FLOAT, VEF_DOUBLE, VEF_LONG_DOUBLE,};//FVF quick-system#define FVF_XYZ 0x00000001#define FVF_NORMAL 0x00000002#define FVF_DIFFUSE 0x00000004#define FVF_SPECULAR 0x00000008#define FVF_TEXTURE0 0x00010000#define FVF_TEXTURE1 0x00020000#define FVF_TEXTURE2 0x00040000#define FVF_TEXTURE3 0x00080000#define FVF_TEXTURE(X) (0x00010000 << (X))//specifies a single part of a vertex, e.g. one position, or one texcoord, etc.struct VertexElement{ unsigned int Stream; unsigned int Count; std::size_t Offset; //offset in the structure VertexElementFormat Format; VertexElementType Type; //normal ctor VertexElement() : Stream( 0 ), Count( 0 ), Format( VEF_FLOAT ), Type( VET_XYZ ), Offset( 0 ) { } //inline ctor for laziness VertexElement( unsigned int vStream, unsigned int vCount, std::size_t vOffset, VertexElementFormat vFormat, VertexElementType vType ) : Stream( vStream ), Count( vCount ), Format( vFormat), Type( vType ), Offset( vOffset ) { } static std::size_t FormatSize( VertexElementFormat vef ); //Compute the size of this element in bytes std::size_t SizeBytes() { return FormatSize( Format ) * Count; }};//specifies a complete vertex, basically just a list of elementsstruct VertexDeclaration{ typedef std::vector<VertexElement> ElementList; typedef ElementList::iterator Iterator; ElementList Elements; VertexDeclaration() { Elements.reserve( 4 ); } static VertexDeclaration CreateFromFVF( unsigned int FVF );};//in D3D, streams will correspond to real streams//in OGL, the streams will be somewhat virtualised, but effectively the same#define MAX_VERTEX_STREAMS 8//holds all the data for a single streamstruct StreamSource{ VertexBuffer* Source; std::size_t Offset; std::size_t Stride; StreamSource() : Source( NULL ), Offset( 0 ), Stride( 0 ) { }};//holds everything geometric about an objectclass Geometry{protected: VertexDeclaration m_Decl; RenderMode m_Mode; std::size_t m_PrimitiveCount; std::size_t m_IndexCount; StreamSource m_Streams[MAX_VERTEX_STREAMS]; IndexBuffer* m_Indices; //if IB is NULL, use non-indexed primitive std::size_t m_IndexOffset; std::size_t m_FirstVertex; std::size_t m_NumVertices;public: Geometry(); virtual ~Geometry(); //Sets the rendering mode and primitive count for this geom void SetRenderMode( RenderMode Mode, std::size_t IndexCount ); //Sets the vertex buffer for the specified stream void SetStreamSource( unsigned int Stream, VertexBuffer* Source, std::size_t Offset, std::size_t Stride ); //Sets the indices for this geom (NULL for no indexing -- Offset is used for VB) void SetIndices( IndexBuffer* Indices, std::size_t Offset ); //Sets the range of vertex used by the indices (ignored if not using indices) void SetRange( std::size_t First, std::size_t Count ); //used to access the vertex declaration VertexDeclaration& Decl() { return m_Decl; } //access the streams StreamSource* Stream( unsigned int Idx ) { assert( Idx < MAX_VERTEX_STREAMS ); return &m_Streams[Idx]; } //access the indices IndexBuffer* Indices() { return m_Indices; } //index buffer offset std::size_t IndexOffset() const { return m_IndexOffset; } //Primitive count std::size_t PrimitiveCount() const { return m_PrimitiveCount; } std::size_t IndexCount() const { return m_IndexCount; } //render mode for this geom RenderMode Mode() const { return m_Mode; } //Get the index range void GetRange( std::size_t& First, std::size_t& Count ) const { First = m_FirstVertex; Count = m_NumVertices; }};#endif
And then the function to parse this into OpenGL goes like this:
void OGLRenderer::BeginRender( Geometry* Geom ){ if( m_RenderBegun ) return; if( Geom == NULL ) return; //keeps track of tex coord sets in use unsigned int TexCoord = 0; //first, get the Geom's declaration and set stuff up VertexDeclaration::Iterator it = Geom->Decl().Elements.begin(); while( it != Geom->Decl().Elements.end() ) { if( m_CurrentVB != Geom->Stream( it->Stream )->Source ) { m_CurrentVB = down_cast<OGLVertexBuffer*>( Geom->Stream( it->Stream )->Source ); if( m_CurrentVB != NULL ) { m_CurrentVB->Bind(); } else if( GLEE_ARB_vertex_buffer_object ) { glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); } } //initialize the pointers for this element GLsizei Stride = (GLsizei) Geom->Stream( it->Stream )->Stride; GLsizei StreamOffset = (GLsizei) Geom->Stream( it->Stream)->Offset; switch( it->Type ) { case VET_XYZ: glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( it->Count, TranslateVertexFormat( it->Format ), Stride, m_CurrentVB->GetPointer() + it->Offset + StreamOffset ); break; case VET_NORMAL: glEnableClientState( GL_NORMAL_ARRAY ); glNormalPointer( TranslateVertexFormat( it->Format ), Stride, m_CurrentVB->GetPointer() + it->Offset + StreamOffset ); break; case VET_DIFFUSE: glEnableClientState( GL_COLOR_ARRAY ); glColorPointer( it->Count, TranslateVertexFormat( it->Format ), Stride, m_CurrentVB->GetPointer() + it->Offset + StreamOffset ); break; case VET_SPECULAR: glEnableClientState( GL_SECONDARY_COLOR_ARRAY ); glSecondaryColorPointer( it->Count, TranslateVertexFormat( it->Format ), Stride, m_CurrentVB->GetPointer() + it->Offset + StreamOffset ); break; case VET_TEXCOORD: glClientActiveTexture( GL_TEXTURE0 + TexCoord ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glTexCoordPointer( it->Count, TranslateVertexFormat( it->Format ), Stride, m_CurrentVB->GetPointer() + it->Offset + StreamOffset ); ++TexCoord; break; } ++it; } //set up indices if we have any if( m_Indices != Geom->Indices() ) { m_Indices = down_cast<OGLIndexBuffer*>( Geom->Indices() ); if( m_Indices != NULL ) { m_Indices->Bind(); } else if( GLEE_ARB_vertex_buffer_object ) { glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, NULL ); } } m_RenderBegun = true; m_CurGeom = Geom;}
(Note: This appears to be an older version of my source. The newer version has some modifications that allow arbitrary VertexElementTypes, which is useful for shader stuff.)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement