From f1ec32bed01ca8462c94b654ab2bc3da51df5f93 Mon Sep 17 00:00:00 2001 From: HuYingzhuo Date: Wed, 27 Mar 2019 16:22:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E6=96=B0BufferData/BufferObject/Verte?= =?UTF-8?q?xArray/Renderable=EF=BC=8C=E5=B9=B6=E6=B5=8B=E8=AF=95DirectGLRe?= =?UTF-8?q?nder=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/DirectGLRender/main.cpp | 30 ++++---- inc/hgl/graph/BufferData.h | 46 +++++++++++-- inc/hgl/graph/BufferObject.h | 111 ++++++++++++++++++++++++++---- inc/hgl/graph/Renderable.h | 1 + inc/hgl/graph/VertexArray.h | 24 +++---- src/RenderDriver/BufferObject.cpp | 80 +-------------------- src/RenderDriver/Renderable.cpp | 24 ++++--- src/RenderDriver/VertexArray.cpp | 8 +-- 8 files changed, 187 insertions(+), 137 deletions(-) diff --git a/example/DirectGLRender/main.cpp b/example/DirectGLRender/main.cpp index f701d0c1..54d01fa5 100644 --- a/example/DirectGLRender/main.cpp +++ b/example/DirectGLRender/main.cpp @@ -2,10 +2,7 @@ #include #include #include -#include -#include -#include -#include +#include using namespace hgl; using namespace hgl::graph; @@ -58,26 +55,28 @@ bool InitShader() return(true); } -VB2f *vb_vertex=nullptr; -VB3f *vb_color=nullptr; +ArrayBuffer *vb_vertex=nullptr; +ArrayBuffer *vb_color=nullptr; VertexArray *va=nullptr; +Renderable *render_obj=nullptr; constexpr float vertex_data[]={0.0f,0.5f, -0.5f,-0.5f, 0.5f,-0.5f }; constexpr float color_data[]={1,0,0, 0,1,0, 0,0,1 }; void InitVertexBuffer() { - vb_vertex=new VB2f(3,vertex_data); - vb_color=new VB3f(3,color_data); + vb_vertex=CreateVBO(VB2f(3,vertex_data)); + vb_color=CreateVBO(VB3f(3,color_data)); - va=new VertexArray(GL_TRIANGLES, //画三角形 - 2); //两个属性 + va=new VertexArray(2); //两个属性 const int vertex_location=shader.GetAttribLocation("Vertex"); ///<取得顶点数据输入流对应的shader地址 const int color_location=shader.GetAttribLocation("Color"); ///<取得颜色数据输入流对应的shader地址 - va->SetVertexBuffer(vertex_location,vb_vertex); - va->SetColorBuffer(color_location,vb_color,HGL_PC_RGB); + va->SetPosition(vertex_location,vb_vertex); + va->AddBuffer(color_location,vb_color); + + render_obj=new Renderable(GL_TRIANGLES,va); } constexpr GLfloat clear_color[4]= @@ -95,7 +94,7 @@ void draw() glClearBufferfv(GL_COLOR,0,clear_color); glClearBufferfv(GL_DEPTH,0,&clear_depth); - va->Draw(); + render_obj->Draw(); } int main(void) @@ -144,6 +143,11 @@ int main(void) win->PollEvent(); //处理窗口事件 } + delete render_obj; + delete va; + delete vb_color; + delete vb_vertex; + delete win; delete device; diff --git a/inc/hgl/graph/BufferData.h b/inc/hgl/graph/BufferData.h index f848c64c..e3eb3948 100644 --- a/inc/hgl/graph/BufferData.h +++ b/inc/hgl/graph/BufferData.h @@ -68,12 +68,12 @@ namespace hgl virtual ~VertexBufferData()=default; - GLenum GetDataType()const { return data_type; } ///<取得数据类型 - uint GetComponent()const { return data_comp; } ///<取数每一组数据中的数据数量 - uint GetStride()const { return data_stride; } ///<取得每一组数据字节数 + GLenum GetDataType ()const{return data_type;} ///<取得数据类型 + uint GetComponent ()const{return data_comp;} ///<取数每一组数据中的数据数量 + uint GetStride ()const{return data_stride;} ///<取得每一组数据字节数 - GLsizeiptr GetCount()const { return data_count; } ///<取得数据数量 - GLsizeiptr GetTotalBytes()const { return total_bytes; } ///<取得数据总字节数 + GLsizeiptr GetCount ()const{return data_count;} ///<取得数据数量 + GLsizeiptr GetTotalBytes ()const{return total_bytes;} ///<取得数据总字节数 }; /** @@ -95,6 +95,42 @@ namespace hgl * @param count 数据数量 */ VertexBufferData *CreateVertexBufferData(void *data,const GLenum &dt,const uint &dbytes,const uint &dcm,const GLsizeiptr &count); + + #define VBDATA_CREATE_FUNC(type,gl_type,short_name) \ + inline VertexBufferData *VB1##short_name(const GLsizeiptr &count){return CreateVertexBufferData(gl_type,sizeof(type),1,count);} \ + inline VertexBufferData *VB2##short_name(const GLsizeiptr &count){return CreateVertexBufferData(gl_type,sizeof(type),2,count);} \ + inline VertexBufferData *VB3##short_name(const GLsizeiptr &count){return CreateVertexBufferData(gl_type,sizeof(type),3,count);} \ + inline VertexBufferData *VB4##short_name(const GLsizeiptr &count){return CreateVertexBufferData(gl_type,sizeof(type),4,count);} \ + \ + inline VertexBufferData *VB1##short_name(const GLsizeiptr &count,const type *data){return CreateVertexBufferData((void *)data,gl_type,sizeof(type),1,count);} \ + inline VertexBufferData *VB2##short_name(const GLsizeiptr &count,const type *data){return CreateVertexBufferData((void *)data,gl_type,sizeof(type),2,count);} \ + inline VertexBufferData *VB3##short_name(const GLsizeiptr &count,const type *data){return CreateVertexBufferData((void *)data,gl_type,sizeof(type),3,count);} \ + inline VertexBufferData *VB4##short_name(const GLsizeiptr &count,const type *data){return CreateVertexBufferData((void *)data,gl_type,sizeof(type),4,count);} + + VBDATA_CREATE_FUNC(int8, GL_BYTE, i8) + VBDATA_CREATE_FUNC(int8, GL_BYTE, b) + VBDATA_CREATE_FUNC(int16, GL_SHORT, i16) + VBDATA_CREATE_FUNC(int16, GL_SHORT, s) + VBDATA_CREATE_FUNC(int32, GL_INT, i32) + VBDATA_CREATE_FUNC(int32, GL_INT, i) + + VBDATA_CREATE_FUNC(uint8, GL_UNSIGNED_BYTE, u8) + VBDATA_CREATE_FUNC(uint8, GL_UNSIGNED_BYTE, ub) + VBDATA_CREATE_FUNC(uint16,GL_UNSIGNED_SHORT, u16) + VBDATA_CREATE_FUNC(uint16,GL_UNSIGNED_SHORT, us) + VBDATA_CREATE_FUNC(uint32,GL_UNSIGNED_INT, u32) + VBDATA_CREATE_FUNC(uint32,GL_UNSIGNED_INT, ui) + + VBDATA_CREATE_FUNC(uint16,GL_HALF_FLOAT, hf) + VBDATA_CREATE_FUNC(uint16,GL_HALF_FLOAT, f16) + VBDATA_CREATE_FUNC(float, GL_FLOAT, f) + VBDATA_CREATE_FUNC(float, GL_FLOAT, f32) + VBDATA_CREATE_FUNC(double,GL_DOUBLE, d) + VBDATA_CREATE_FUNC(double,GL_DOUBLE, f64) + #undef VBDATA_CREATE_FUNC + + inline VertexBufferData *EB16(const uint16 &count){return CreateVertexBufferData(GL_UNSIGNED_SHORT, 2,1,count);} + inline VertexBufferData *EB32(const uint32 &count){return CreateVertexBufferData(GL_UNSIGNED_INT, 4,1,count);} }//namespace graph }//namespace hgl #endif//HGL_GRAPH_BUFFER_DATA_INCLUDE diff --git a/inc/hgl/graph/BufferObject.h b/inc/hgl/graph/BufferObject.h index 4bb0f222..12c313f1 100644 --- a/inc/hgl/graph/BufferObject.h +++ b/inc/hgl/graph/BufferObject.h @@ -38,30 +38,24 @@ namespace hgl public: // bool Create (GLsizeiptr,GLenum up); ///<创建数据区 - bool Submit (void *,GLsizeiptr,GLenum up); ///<提交数据 - bool Submit (const BufferData *buf_data,GLenum up); ///<提交数据 + bool Submit (void *,GLsizeiptr,GLenum up=GL_STATIC_DRAW); ///<提交数据 + bool Submit (const BufferData *,GLenum up=GL_STATIC_DRAW); ///<提交数据 bool Change (void *,GLsizeiptr,GLsizeiptr); ///<修改数据 };//class BufferObject - BufferObject *CreateBufferObject(const GLenum &type,const GLenum &user_pattern=0,BufferData *buf=nullptr); ///<创建一个缓冲区对象 - BufferObject *CreateBufferObject(const GLenum &buf_type,const GLenum &user_pattern,const GLsizeiptr &total_bytes); ///<创建一个缓冲区对象 - BufferObject *CreateBufferObject(const GLenum &buf_type,const GLenum &user_pattern,const GLsizeiptr &total_bytes,void *data); ///<创建一个缓冲区对象 - /** * 显存顶点属性数据缓冲区对象 */ class VertexBufferObject:public BufferObject { - const VertexBufferData *vertex_buffer_data; - public: using BufferObject::BufferObject; ~VertexBufferObject()=default; - const VertexBufferData *GetVertexBufferData()const { return vertex_buffer_data; } + const VertexBufferData *GetVertexBufferData()const{return (const VertexBufferData *)buffer_data;} - #define VBD_FUNC_COPY(type,name) type Get##name()const{return vertex_buffer_data?vertex_buffer_data->Get##name():0;} + #define VBD_FUNC_COPY(type,name) type Get##name()const{return buffer_data?((const VertexBufferData *)buffer_data)->Get##name():0;} VBD_FUNC_COPY(GLenum,DataType) VBD_FUNC_COPY(uint,Component) @@ -71,11 +65,100 @@ namespace hgl #undef VBD_FUNC_COPY };//class VertexBufferObject:public BufferObject - VertexBufferObject *CreateVertexBufferObject(const GLenum &type,const GLenum &user_pattern=0,VertexBufferData *buf=nullptr); ///<创建一个顶点缓冲区对象 - VertexBufferObject *CreateVertexBufferObject(const GLenum &buf_type,const GLenum &user_pattern,const GLsizeiptr &total_bytes); ///<创建一个顶点缓冲区对象 - VertexBufferObject *CreateVertexBufferObject(const GLenum &buf_type,const GLenum &user_pattern,const GLsizeiptr &total_bytes,void *data); ///<创建一个顶点缓冲区对象 + /** + * 创建一个缓冲区对象 + * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) + * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) + * @param buf 数据缓冲区 + */ + template + inline BO *_CreateBufferObject(BD *buf=nullptr,const GLenum &user_pattern=GL_STATIC_DRAW) + { + BO *obj=new BO(); - using ElementBufferObject=VertexBufferObject; + if(buf) + obj->Submit(buf,user_pattern); + + return(obj); + } + + ///** + // * 创建一个缓冲区对象 + // * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) + // * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) + // * @param total_bytes 数据总字节数 + // */ + //template + //inline BO *_CreateBufferObject(const GLenum &buf_type,const GLenum &user_pattern,const GLsizeiptr &total_bytes) + //{ + // if(total_bytes<=0)return(nullptr); + + // BO *buf=new BO(buf_type); + + // //if(buf->Create(total_bytes,user_pattern)) + // // return buf; + + // delete buf; + // return(nullptr); + //} + + /** + * 创建一个缓冲区对象 + * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) + * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) + * @param total_bytes 数据总字节数 + * @param data 数据指针 + */ + template + inline BO *_CreateBufferObject(void *data,const GLsizeiptr &total_bytes,const GLenum &user_pattern=GL_STATIC_DRAW) + { + if(total_bytes<=0)return(nullptr); + if(!data)return(nullptr); + + BO *buf=new BO(); + + //if(buf->Create(total_bytes,user_pattern)) + // return buf; + + if(buf->Submit(data,total_bytes,user_pattern)) + return buf; + + delete buf; + return(nullptr); + } + + #define VBCLASS_DEF(buffer_gl_type,buffer_class_name,BASE,data_name,short_name) \ + class buffer_class_name:public BASE \ + { \ + public: \ + \ + buffer_class_name():BASE(buffer_gl_type){} \ + ~buffer_class_name()=default; \ + }; \ + \ + inline buffer_class_name *Create##short_name() \ + { \ + return(new buffer_class_name()); \ + }; \ + \ + inline buffer_class_name *Create##short_name(data_name *buf=nullptr,const GLenum user_pattern=GL_STATIC_DRAW) \ + { \ + return _CreateBufferObject(buf,user_pattern); \ + }; \ + \ + inline buffer_class_name *Create##short_name(void *data,const GLsizeiptr &size,const GLenum &user_pattern=GL_STATIC_DRAW) \ + { \ + return _CreateBufferObject(data,size,user_pattern); \ + } + + //ps.在这里用宏了再用模板本是多此一举,但使用模板函数易于调试器中进行逐行调试,同时因为INLINE编译编译器也会自动展开代码,不用担心效率 + + VBCLASS_DEF(GL_ARRAY_BUFFER, ArrayBuffer, VertexBufferObject, VertexBufferData, VBO) + VBCLASS_DEF(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer, VertexBufferObject, VertexBufferData, EBO) + VBCLASS_DEF(GL_UNIFORM_BUFFER, UniformBuffer, BufferObject, BufferData, UBO) + VBCLASS_DEF(GL_SHADER_STORAGE_BUFFER, ShaderStorageBuffer,BufferObject, BufferData, SSBO) + + #undef VBCLASS_DEF }//namespace graph }//namespace hgl #endif//HGL_GRAPH_BUFFER_OBJECT_INCLUDE diff --git a/inc/hgl/graph/Renderable.h b/inc/hgl/graph/Renderable.h index 1eb63dff..f029b2dd 100644 --- a/inc/hgl/graph/Renderable.h +++ b/inc/hgl/graph/Renderable.h @@ -2,6 +2,7 @@ #define HGL_GRAPH_RENDERABLE_INCLUDE #include +#include namespace hgl { diff --git a/inc/hgl/graph/VertexArray.h b/inc/hgl/graph/VertexArray.h index f3fddf19..17647268 100644 --- a/inc/hgl/graph/VertexArray.h +++ b/inc/hgl/graph/VertexArray.h @@ -17,16 +17,16 @@ namespace hgl GLuint vao; - ObjectList vbo_list; ///<顶点数据缓冲区 + List vbo_list; ///<顶点数据缓冲区 - ElementBufferObject *element_buffer; + ElementBuffer *element_buffer; - VertexBufferObject *position_buffer; + ArrayBuffer *position_buffer; int position_compoment; ///<位置属性格式 public: - VertexArray(uint max_vertex_attrib); + VertexArray(GLint max_vertex_attrib); ~VertexArray(); static int GetMaxVertexAttrib(); @@ -35,18 +35,18 @@ namespace hgl public: //通用顶点缓冲区设置 - int AddBuffer (int shader_location,VertexBufferObject *); ///<设置顶点缓冲区对象 - VertexBufferObject *GetBuffer (int index){return vbo_list[index];} ///<取得顶点缓冲区对象 - bool ClearBuffer (int index){return vbo_list.Delete(index);} ///<清除顶点缓冲区对象 - void ClearBuffers(){ vbo_list.Clear();} ///<清除所有顶点缓冲区对象 + int AddBuffer (int shader_location,ArrayBuffer *); ///<设置顶点缓冲区对象 + ArrayBuffer * GetBuffer (int index){return GetObject(vbo_list,index);} ///<取得顶点缓冲区对象 + bool ClearBuffer (int index){return vbo_list.Delete(index);} ///<清除顶点缓冲区对象 + void ClearBuffers(){ vbo_list.Clear();} ///<清除所有顶点缓冲区对象 public: //特殊缓冲区独立设置函数 - bool SetElement (ElementBufferObject *eb); ///<设置索引缓冲区对象 - bool SetPosition (int shader_location,VertexBufferObject *vb); ///<设置位置缓冲区对象 + bool SetElement (ElementBuffer *eb); ///<设置索引缓冲区对象 + bool SetPosition (int shader_location,ArrayBuffer *vb); ///<设置位置缓冲区对象 - ElementBufferObject * GetElement (){return element_buffer;} ///<获取索引缓冲区对象 - VertexBufferObject * GetPosition (){return position_buffer;} ///<获取位置缓冲区对象 + ElementBuffer * GetElement (){return element_buffer;} ///<获取索引缓冲区对象 + ArrayBuffer * GetPosition (){return position_buffer;} ///<获取位置缓冲区对象 };//class VertexArray }//namespace graph }//namespace hgl diff --git a/src/RenderDriver/BufferObject.cpp b/src/RenderDriver/BufferObject.cpp index 4ebfc82d..093ece1c 100644 --- a/src/RenderDriver/BufferObject.cpp +++ b/src/RenderDriver/BufferObject.cpp @@ -148,13 +148,14 @@ namespace hgl bool BufferObject::Submit(const BufferData *buf_data,GLenum up) { if(!buf_data)return(false); - buffer_data=buf_data; void * data=buf_data->GetData(); GLsizeiptr size=buf_data->GetTotalBytes(); if(!data||size<=0)return(false); + buffer_data=buf_data; + return Submit(data,size,up); } @@ -167,81 +168,4 @@ namespace hgl return(true); } }//namespace graph - - namespace graph - { - - /** - * 创建一个缓冲区对象 - * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) - * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) - * @param buf 数据缓冲区 - */ - template - BO *_CreateBufferObject(const GLenum &buf_type,const GLenum &user_pattern,BD *buf) - { - BO *obj=new BO(buf_type); - - if(buf) - obj->Submit(buf,user_pattern); - - return(obj); - } - - /** - * 创建一个缓冲区对象 - * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) - * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) - * @param total_bytes 数据总字节数 - */ - template - BO *_CreateBufferObject(const GLenum &buf_type, - const GLenum &user_pattern, - const GLsizeiptr &total_bytes) - { - if(total_bytes<=0)return(nullptr); - - BO *buf=new BO(buf_type); - - //if(buf->Create(total_bytes,user_pattern)) - // return buf; - - delete buf; - return(nullptr); - } - - /** - * 创建一个缓冲区对象 - * @param buf_type 缓冲区类型(GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER等) - * @param user_pattern 数据存储区使用模式(GL_STATIC_DRAW,GL_DYNAMIC_DRAW等) - * @param total_bytes 数据总字节数 - * @param data 数据指针 - */ - template - inline BO *_CreateBufferObject( const GLenum &buf_type, - const GLenum &user_pattern, - const GLsizeiptr &total_bytes,void *data) - { - if(total_bytes<=0)return(nullptr); - if(!data)return(nullptr); - - BO *buf=new BO(buf_type); - - //if(buf->Create(total_bytes,user_pattern)) - // return buf; - - if(buf->Submit(data,total_bytes,user_pattern)) - return buf; - - delete buf; - return(nullptr); - } - - BufferObject *CreateBufferObject(const GLenum &type,const GLenum &up,BufferData *buf) { return _CreateBufferObject(type,up,buf); } - BufferObject *CreateBufferObject(const GLenum &type,const GLenum &up,const GLsizeiptr &size) { return _CreateBufferObject(type,up,size); } - BufferObject *CreateBufferObject(const GLenum &type,const GLenum &up,const GLsizeiptr &size,void *data) { return _CreateBufferObject(type,up,size,data); } - VertexBufferObject *CreateVertexBufferObject(const GLenum &type,const GLenum &up,VertexBufferData *buf) { return _CreateBufferObject(type,up,buf); } - VertexBufferObject *CreateVertexBufferObject(const GLenum &type,const GLenum &up,const GLsizeiptr &size) { return _CreateBufferObject(type,up,size); } - VertexBufferObject *CreateVertexBufferObject(const GLenum &type,const GLenum &up,const GLsizeiptr &size,void *data) { return _CreateBufferObject(type,up,size,data); } - }//namespace graph }//namespace hgl diff --git a/src/RenderDriver/Renderable.cpp b/src/RenderDriver/Renderable.cpp index a41685da..23eb580e 100644 --- a/src/RenderDriver/Renderable.cpp +++ b/src/RenderDriver/Renderable.cpp @@ -10,35 +10,37 @@ namespace hgl */ uint Renderable::GetDrawCount() { - ElementBufferObject *obj=vao->GetElement(); + ElementBuffer *eb=vao->GetElement(); - if(!obj) - obj=vao->GetPosition(); + if(eb) + return eb->GetCount(); - if(!obj) + ArrayBuffer *pb=vao->GetPosition(); + + if(!pb) return 0; - return obj->GetCount(); + return pb->GetCount(); } bool Renderable::Draw() { glBindVertexArray(vao->GetVAO()); - ElementBufferObject *element_buffer=vao->GetElement(); + ElementBuffer *eb=vao->GetElement(); - if(!element_buffer) + if(!eb) { - VertexBufferObject *position_buffer=vao->GetPosition(); + ArrayBuffer *pb=vao->GetPosition(); - if(!position_buffer) + if(!pb) return(false); - glDrawArrays(primitive,0,position_buffer->GetCount()); + glDrawArrays(primitive,0,pb->GetCount()); } else { - glDrawElements(primitive,element_buffer->GetCount(),element_buffer->GetDataType(),nullptr); + glDrawElements(primitive,eb->GetCount(),eb->GetDataType(),nullptr); } return(true); diff --git a/src/RenderDriver/VertexArray.cpp b/src/RenderDriver/VertexArray.cpp index 46de4d65..807569e3 100644 --- a/src/RenderDriver/VertexArray.cpp +++ b/src/RenderDriver/VertexArray.cpp @@ -18,7 +18,7 @@ namespace hgl return HGL_MAX_VERTEX_ATTRIBS; } - VertexArray::VertexArray(uint max_vertex_attrib) + VertexArray::VertexArray(GLint max_vertex_attrib) { if(max_vertex_attrib>GetMaxVertexAttrib()) max_vertex_attrib=HGL_MAX_VERTEX_ATTRIBS; @@ -42,7 +42,7 @@ namespace hgl * @return 绑定点索引 * @return -1 失败 */ - int VertexArray::AddBuffer(int shader_location,VertexBufferObject *vb) + int VertexArray::AddBuffer(int shader_location,ArrayBuffer *vb) { if(!vb)return(false); if(vb->GetBufferType()!=GL_ARRAY_BUFFER)return(false); @@ -66,7 +66,7 @@ namespace hgl /** * 设置索引缓冲区 */ - bool VertexArray::SetElement(ElementBufferObject *eb) + bool VertexArray::SetElement(ElementBuffer *eb) { if(!eb)return(false); if(eb->GetBufferType()!=GL_ELEMENT_ARRAY_BUFFER)return(false); @@ -81,7 +81,7 @@ namespace hgl * @param shader_location 这个缓冲区对应的SHADER地址 * @param vb 数据缓冲区 */ - bool VertexArray::SetPosition(int shader_location,VertexBufferObject *vb) + bool VertexArray::SetPosition(int shader_location,ArrayBuffer *vb) { if(!vb)return(false);