#include "cvertexbuffervbo.hpp" #include "glhelper.hpp" #include "renderer/crenderergl3.hpp" namespace EE { namespace Graphics { cVertexBufferVBO::cVertexBufferVBO( const Uint32& VertexFlags, EE_DRAW_MODE DrawType, const Int32& ReserveVertexSize, const Int32& ReserveIndexSize, EE_VBO_USAGE_TYPE UsageType ) : cVertexBuffer( VertexFlags, DrawType, ReserveVertexSize, ReserveIndexSize, UsageType ), mCompiled( false ), mBuffersSet( false ), mTextured( false ), mVAO( 0 ), mElementHandle( 0 ) { } cVertexBufferVBO::~cVertexBufferVBO() { for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) { if( VERTEX_FLAG_QUERY( mVertexFlags, i ) ) { glDeleteBuffersARB( 1,(GLuint *)&mArrayHandle[ i ] ); } } if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) { glDeleteBuffersARB( 1, (GLuint *)&mElementHandle ); } #if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU if ( GLv_3 == GLi->Version() ) { glDeleteVertexArrays( 1, &mVAO ); } #endif } void cVertexBufferVBO::Bind() { if ( !mCompiled ) { Compile(); if ( !mCompiled ) return; } SetVertexStates(); } bool cVertexBufferVBO::Compile() { if( mCompiled ) return false; #if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU if ( GLv_3 == GLi->Version() ) { glGenVertexArrays( 1, &mVAO ); glBindVertexArray( mVAO ); } #endif GLenum usageType = GL_STATIC_DRAW; if( mUsageType== VBO_USAGE_TYPE_DYNAMIC ) usageType = GL_DYNAMIC_DRAW; else if( mUsageType== VBO_USAGE_TYPE_STREAM ) usageType = GL_STREAM_DRAW; //Create the VBO vertex arrays for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) { if( VERTEX_FLAG_QUERY( mVertexFlags, i ) ) { glGenBuffersARB( 1,(GLuint *)&mArrayHandle[ i ] ); glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[i] ); if ( mArrayHandle[i] ) { if ( i != VERTEX_FLAG_COLOR ) glBufferDataARB( GL_ARRAY_BUFFER, mVertexArray[i].size() * sizeof(eeFloat), &( mVertexArray[i][0] ), usageType ); else glBufferDataARB( GL_ARRAY_BUFFER, mColorArray.size(), &mColorArray[0], usageType ); } else { return false; } } } glBindBuffer( GL_ARRAY_BUFFER, 0 ); //Create the VBO index array if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) { glGenBuffersARB( 1, (GLuint *)&mElementHandle ); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle ); glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, GetIndexCount() * sizeof(Uint32), &mIndexArray[0], usageType ); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 ); } mCompiled = true; mBuffersSet = false; return true; } void cVertexBufferVBO::Draw() { if ( !mCompiled ) return; if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { #if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU glBindVertexArray( mVAO ); #endif if ( !mTextured ) { GLi->Disable( GL_TEXTURE_2D ); } } if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) { Int32 lSize = mElemDraw; if( mElemDraw < 0 ) lSize = GetIndexCount(); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle ); glDrawElements( mDrawType, lSize, GL_UNSIGNED_INT, (char*)NULL ); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 ); } else { glDrawArrays( mDrawType, 0, GetVertexCount() ); } if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { if ( !mTextured ) { GLi->Enable( GL_TEXTURE_2D ); } } } void cVertexBufferVBO::SetVertexStates() { GLint index; #if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU if ( GLv_3 == GLi->Version() ) { if ( mBuffersSet ) { return; } glBindVertexArray( mVAO ); } #endif /// POSITION if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_POSITION ) ) { GLi->EnableClientState( GL_VERTEX_ARRAY ); glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_POSITION ] ); #ifdef EE_GL3_ENABLED if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { index = GLi->GetRendererGL3()->GetStateIndex( EEGL_VERTEX_ARRAY ); if ( -1 != index ) { glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_POSITION ], GL_FLOAT, GL_FALSE, 0, 0 ); } } else #endif { GLi->VertexPointer( eeVertexElements[ VERTEX_FLAG_POSITION ], GL_FLOAT, 0, (char*)NULL, 0 ); } } else { GLi->DisableClientState( GL_VERTEX_ARRAY ); } /// COLOR if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_COLOR ) ) { GLi->EnableClientState( GL_COLOR_ARRAY ); glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_COLOR ] ); #ifdef EE_GL3_ENABLED if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { index = GLi->GetRendererGL3()->GetStateIndex( EEGL_COLOR_ARRAY ); if ( -1 != index ) glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_COLOR ], GL_UNSIGNED_BYTE, GL_TRUE, 0, 0 ); } else #endif { GLi->ColorPointer( eeVertexElements[ VERTEX_FLAG_COLOR ], GL_UNSIGNED_BYTE, 0, (char*)NULL, 0 ); } } else { GLi->DisableClientState( GL_COLOR_ARRAY ); } /// TEXTURES if ( GLi->IsExtension( EEGL_ARB_multitexture ) ) { for ( Int32 i = 0; i < EE_MAX_TEXTURE_UNITS; i++ ) { if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 + i ) ) { GLi->ClientActiveTexture( GL_TEXTURE0 + i ); GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY ); glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_TEXTURE0 + i ] ); #ifdef EE_GL3_ENABLED if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { index = GLi->GetRendererGL3()->GetStateIndex( EEGL_TEXTURE_COORD_ARRAY ); if ( -1 != index && 0 == i ) glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_TEXTURE0 + i ], GL_FLOAT, GL_FALSE, 0, 0 ); } else #endif { GLi->TexCoordPointer( eeVertexElements[ VERTEX_FLAG_TEXTURE0 + i ], GL_FLOAT, 0, (char*)NULL, 0 ); } mTextured = true; } else { GLi->DisableClientState( GL_TEXTURE_COORD_ARRAY ); GLi->Disable( GL_TEXTURE_2D ); mTextured = false; break; } } } else { if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 ) ) { GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY ); glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_TEXTURE0 ] ); #ifdef EE_GL3_ENABLED if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) { index = GLi->GetRendererGL3()->GetStateIndex( EEGL_TEXTURE_COORD_ARRAY ); if ( -1 != index ) glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_TEXTURE0 ], GL_FLOAT, GL_FALSE, 0, 0 ); } else #endif { GLi->TexCoordPointer( eeVertexElements[ VERTEX_FLAG_TEXTURE0 ], GL_FLOAT, 0, (char*)NULL, 0 ); } mTextured = true; } else { GLi->Disable( GL_TEXTURE_2D ); GLi->DisableClientState( GL_TEXTURE_COORD_ARRAY ); mTextured = false; } } GLi->ActiveTexture( GL_TEXTURE0 ); GLi->ClientActiveTexture( GL_TEXTURE0 ); glBindBufferARB( GL_ARRAY_BUFFER, 0 ); mBuffersSet = true; } void cVertexBufferVBO::Update( const Uint32& Types, bool Indices ) { GLenum usageType = GL_STATIC_DRAW; if( mUsageType== VBO_USAGE_TYPE_DYNAMIC ) usageType = GL_DYNAMIC_DRAW; else if( mUsageType== VBO_USAGE_TYPE_STREAM ) usageType = GL_STREAM_DRAW; for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) { if ( VERTEX_FLAG_QUERY( mVertexFlags, i ) && VERTEX_FLAG_QUERY( Types, i ) ) { glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[i] ); if ( mArrayHandle[i] ) { if ( i != VERTEX_FLAG_COLOR ) glBufferDataARB( GL_ARRAY_BUFFER, mVertexArray[i].size() * sizeof(eeFloat), &( mVertexArray[i][0] ), usageType ); else glBufferDataARB( GL_ARRAY_BUFFER, mColorArray.size(), &mColorArray[0], usageType ); } } } glBindBuffer( GL_ARRAY_BUFFER, 0 ); if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) && Indices ) { glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle ); glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, GetIndexCount() * sizeof(Uint32), &mIndexArray[0], usageType ); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 ); } mBuffersSet = false; } void cVertexBufferVBO::Reload() { mCompiled = false; mBuffersSet = false; Compile(); } void cVertexBufferVBO::Unbind() { #ifdef EE_GL3_ENABLED if ( GLv_3 == GLi->Version() ) { GLi->GetRendererGL3()->BindGlobalVAO(); } else #endif { if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_POSITION ) ) { GLi->EnableClientState( GL_VERTEX_ARRAY ); } if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_COLOR ) ) { GLi->EnableClientState( GL_COLOR_ARRAY ); } if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 ) ) { GLi->Enable( GL_TEXTURE_2D ); GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY ); } } } }}