VertexArray EECS487:Interactive ComputerGraphics Lecture17: • VertexBufferObject(VBO) • Vertex-ArrayObject(VAO) • Samplecodeat http://web.eecs.umich.edu/~sugih/courses/eecs487/common/notes/gl3+webgl.tgz Vertexarraymustbecopiedoneverydraw VBOallowsdatatobestoredinGPUmemorybutstill clientread/write-able 1. GenerateandbindVBOdescriptor(s) glGenBuffers(),glBindBuffer() 2. AllocatespaceforVBOandpopulateitwithvertex attribute(s)data glBufferData(),glBufferSubData() 3. TelltheGPUwhichattributeiswhereontheVBO glEnableClientState(),glVertexPointer() vertices[] OpenGLstate GL_COLOR_ARRAY App/ClientMemory systembus/network VertexBufferObject(VBO) StepstosetupanduseaVBO: GL_VERTEX_ARRAY GraphicsCard/ ServerMemory color[] Vertexattributedata readfromclient memorytoserver memorywhenever glDraw*()iscalled Seeva.cpp BufferObjectDescriptor First,generatebufferobjectdescriptor(s)*: int vbods[N]; glGenBuffers(GLsizei N, GLuint *vbods); forexample,ifonly1bufferobjectisneeded: int vbod; glGenBuffers(1, &vbod); *descriptor==handle==name==id VertexBufferObject App/ClientMemory CurrentBufferObject OpenGLstate glGenBuffers() vbod Nextbindeachdescriptortoatypeofbuffer glBindBuffer(GLenum target, GLuint vbod); // target: GL_ARRAY_BUFFER, // GL_ELEMENT_ARRAY_BUFFER (for indices) vbo objectholders forexample: glBindBuffer(GL_ARRAY_BUFFER, vbod); systembus/network Thisalsomakesthevbodbufferobjectthe “current/in-use”bufferobject:allsubsequent bufferobjectoperationsapplytothisbufferobject GraphicsCard/ ServerMemory IfvbodisNULL,disableBufferObject VertexBufferObject App/ClientMemory vbod GL_ARRAY_BUFFER vbo objectholders systembus/network OpenGLstate glGenBuffers() glBindBuffer() BufferObjectData Allocated(andinitialize)spaceforbufferobject: glBufferData(GLenum target, GLsizei size, GLvoid* data, GLenum usage); // target:asbefore, size:sizeofdata, // data:pointertosourcedataarray,NULLtoallocate // memorywithoutcontentinitialization // usage:willdatabemodified?HelpsOpenGLdetermine // memorylocationtooptimizeperformance forexample: GraphicsCard/ ServerMemory float vertices[3][2] = { {0.0, 0.0}, {0.0, 1.0}, {1.0, 0.0} }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); VertexBufferObject OpenGLstate App/ClientMemory vbod GL_ARRAY_BUFFER vbo vertices[] glGenBuffers() glBindBuffer() glBufferData() MultipleVertexAttributes Iftherearemultiplevertexattributes,wecanputthem backtobackinthebufferobjectusing: glBufferSubData(GLenum target, GLint offset, GLsizei size, GLvoid* data); objectholders systembus/network vertices[] GraphicsCard/ ServerMemory Vertexattributedata copiedfromclientmemory toservermemoryusing glBufferData()or glBufferSubData() WhenglDraw*()iscalled, dataisalreadyresident MultipleVertexAttributesExample float vertices[3][2] = { {0.0, 0.0}, {0.0, 1.0}, {1.0, 0.0} }; float color[3][3]= { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(color), NULL, GL_STATIC_DRAW); // allocate space only glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // copy data glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(color), color); // copy data // target:asbefore,offset:byteoffsetfromthe // startofbufferascopytarget,size:sizeofdata, // data:pointertosourcedataarray Toavoidhavingtwocopiesofdata,clientcan shareservermemoryusingglMapBuffer()/ glUnmapBuffer()afterthecalltoglBufferData() (seePixelBufferObject(PBO)later) VertexBufferObject OpenGLstate App/ClientMemory vbod GL_ARRAY_BUFFER vbo vertices[] color[] glGenBuffers() glBindBuffer() glBufferData() glBufferSubData() objectholders systembus/network vertices[] color[] GraphicsCard/ ServerMemory Vertexattributedata copiedfromclientmemory toservermemoryusing glBufferData()or glBufferSubData() WhenglDraw*()iscalled, dataisalreadyresident CommonError glGenBuffers()notcalledbeforeglBindBuffer() Offsetisgivenincount,notinbytes,e.g.,ifthefirst array(atoffset0)isofNelementsofclassVertex, thecorrectoffsettothesecondarrayis: N*sizeof(Vertex),notjustN Ifoffsetiswrong,especiallywhenusing glMapBuffer,GPUcanlockupand systemmustberebooted VertexBufferObjectUse Totellthegraphicspipelinethatwe’repassingitan arrayofvertices,aswithvertexarray,enable GL_VERTEX_ARRAYinclientmemory: • glEnableClientState(GL_VERTEX_ARRAY) Next,passthearray,specifyingthedataformat used(differentfromvertexarray,thelastargument isabyteoffsetfromthestartofbuffer) • glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *offset); // size:#coordinatespervertex,type:datatype, // stride=0meanscoordinatesarebacktoback, // offset:byteoffsetfromthestartofbufferobject Finally,drawaswithvertexarray VertexBufferObjectUse Allwehavedonesofariscopiedthevertices[] andcolor[]arraystoabufferobject Thegraphicspipelinehasnoideaoftheexistenceof thebufferobjectnorwhatiscontainedinit Weneedto: 1. tellthegraphicspipelinewhatisinthebufferobject 2. passthebufferobjecttothegraphicspipeline VertexBufferObjectUseExample glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, 0); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, sizeof(vertices)); glDrawArrays(GL_TRIANGLES, 0, 3); // start index: 0 // number of elements: 3 Withvertexbufferobject,client-sidedataarray (vertices[]andcolor[])donotneedtobein scopewhenglDraw*()iscalled VertexBufferObject Seevbo.cpp OpenGLstate App/ClientMemory vbod vbo objectholders GL_ARRAY_BUFFER GL_VERTEX_ARRAY GL_COLOR_ARRAY systembus/network vertices[] color[] GraphicsCard/ ServerMemory glGenBuffers() vertices[] color[] glBindBuffer() glBuffer[Sub]Data() glEnableClientState() glVertexPointer() glColorPointer() Vertexattributedata copiedfromclientmemory toservermemoryusing glBufferData()or glBufferSubData() WhenglDraw*()iscalled, dataisalreadyresident VariousOpenGLObjects BufferObjects:unformattedlinearmemory • VertexBufferObjects • PixelBufferObjects • UniformBufferObjects VertexArrayObjects:encapsulatesetsofvertex arraystatesincludingvbobindings TextureObjects:anOpenGLobjectthatcontains oneormoreimageswiththesameimageformat FramebufferObjects • RenderbufferObjects OpenGLObjectInGeneral OpenGLisastatemachine AnOpenGLobjectisacontainerthatencapsulatesa particularsetofstates ThesetofstatesanOpenGLobjectcontaindependsonthe contextitisboundto:thestatesthatanobjectcontainsare mappedintoandbecomethecontext’sstates,e.g., glBindBuffer(GL_ARRAY_BUFFER, vbod); Toreadmore: http://www.opengl.org/wiki/OpenGL_Objects http://www.opengl.org/wiki/Buffer_Objects http://www.opengl.org/wiki/Vertex_Buffer_Object OpenGLObjectsManagement AllOpenGLobjectsaremanagedthesameway: • glGen*() • glBind*() • use • glDelete*() • assoonasobjectusageisdone,alwayscallglBind*()with objecthandle0tounbindobjectandcallglDelete*()to deleteobject[I’llassumeyouknowthisalreadyandwon’tbe mentioningitagain] DrawingMultipleShapes Todrawdifferentshapes,e.g.,cube,sphere,cone, etc.multipletimes,wanttostorethevertex attributesofeachshapeonceONLY,withre-use Eventhen,withVBOalone,mustmakeseveralAPI callstochangeOpenGLstateforeachshape,each draw: glBindBuffer(GL_ARRAY_BUFFER, vbods[i]); glVertexPointer(2, GL_FLOAT, 0, vertex_offset); glColorPointer(3, GL_FLOAT, 0, color_offset); Vertex-ArrayObject Vertex-ArrayObject(VAO)encapsulates vertexattributestates • format,type,stride,storageinfo,and • attachedvertexbufferobjectifvboisused Enablesrapidswitchingbetweensetsof vertexarraystatesandvbobindingswith asingleAPIcall,changingoneOpenGLstate: glBindVertexArray(vaods[i]); RequiresOpenGL3.0+ Vertex-ArrayObject AswithotherOpenGLobjects,firstgenerate vertex-arrayobjectdescriptor(s)/handle(s): VertexArrayObjectwithoutVBO vaods cone cone vao GLuint vaods[N]; glGenVertexArrays(GLsizei N, GLuint *vaods); forexample,ifonly2vertex-arrayobjectsareneeded: App/ClientMemory GLuint vaods[2]; glGenVertexArrays(2, vaods); Nextbindandmakecurrenteachdescriptor glBindVertexArray(GLuint vaods[int i]); IfvaodsisNULL,disableVertex-ArrayObject GraphicsCard/ ServerMemory vertices[] VAOw/oVBOis supportedbyMacOSX, butnotbyallother graphicscarddrivers OpenGLstate current/ bound SetupClient-SideVertexArray Forcurrent/boundvertex-arrayobject, populateVAObyenablingclient-sideaccess: glEnableClientState(GL_VERTEX_ARRAY); thenspecifyvertexarraylocation: glVertexPointer(2, GL_FLOAT, 0, vertices); Bothclientstateandvertexarraylocation abovearesetwithinthecontextofaVAO VAOw/oVBOissupportedbyMacOSX, Thendraw: butnotbyallothergraphicscarddrivers VertexArrayObjectwithoutVBO vaods cone cone vertices[] vao GL_VERTEX_ARRAY VAOw/oVBOis supportedbyMacOSX, butnotbyallother graphicscarddrivers GL_COLOR_ARRAY App/ClientMemory Vertexattributedataread fromclientmemoryto servermemorywhenever glDraw*()iscalled GraphicsCard/ ServerMemory glDrawArrays(GL_TRIANGLES, 0, 3); VAOsSwitchingExample float cone[N][3], ccolors[N][3]; float cube[M][3], bcolors[M][3]; vaods cone cube // set up: assuming vaods[] have been generated glBindVertexArray(vaods[CONE]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, cone); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, ccolors); glBindVertexArray(vaods[CUBE]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, cube); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, bcolors); // use: cone[], ccolors[], cube[], glBindVertexArray(vaods[CONE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, glBindVertexArray(vaods[CUBE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, glBindVertexArray(vaods[CONE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, VertexArrayObjectwithoutVBO VAOw/oVBOis supportedbyMac OSX,butnotbyall othergraphicscard drivers and bcolors[] must be in scope N); M); N); cone vao vao GL_VERTEX_ARRAY GL_VERTEX_ARRAY GL_COLOR_ARRAY GL_COLOR_ARRAY App/ClientMemory VAOw/oVBOis GraphicsCard/ supportedbyMacOSX, ServerMemory butnotbyallother graphicscarddrivers vertices[] color[] cube vertices[] color[] Vertexattributedataread fromclientmemoryto servermemorywhenever glDraw*()iscalled Seevao-va.cpp VAOwithVBO First,SetupVBO Vertex-ArrayObjectwithVBO float cone[N][3], ccolors[N][3]; float cube[M][3], bcolors[M][3]; enum {CONE=0, CUBE, NSHAPES}; cone vertices[] color[] GLuint vbods[NSHAPES]; glGenBuffers(NSHAPES, vbods); // set up the two vertex buffer objects glBindBuffer(GL_ARRAY_BUFFER, vbods[CONE]); glBufferData(GL_ARRAY_BUFFER, sizeof(cones)+sizeof(ccolors), 0, GL_STATIC_DRAW)); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cone), cone); glBufferSubData(GL_ARRAY_BUFFER, sizeof(cone), sizeof(ccolors), ccolors); glBindBuffer(GL_ARRAY_BUFFER, vbods[CUBE]); glBufferData(GL_ARRAY_BUFFER, sizeof(cube)+sizeof(bcolors), 0, GL_STATIC_DRAW)); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cube), cube); glBufferSubData(GL_ARRAY_BUFFER, sizeof(cube), sizeof(bcolors), bcolors); Next,SetupVAOs GLuint vaods[NSHAPES]; glGenVertexArrays(NSHAPES, vaods); // set up the two vertex-array objects glBindVertexArray(vaods[CONE]); glBindBuffer(GL_ARRAY_BUFFER, vbods[CONE]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0 /* buffer byte offset */); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, sizeof(cone) /* byte offset */); glBindVertexArray(vaods[CUBE]); glBindBuffer(GL_ARRAY_BUFFER, vbods[CONE]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0 /* byte offset */); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, sizeof(cube) /* byte offset */); cube vbods cone cube vertices[] App/ClientMemory color[] vertices[] color[] vertices[] color[] GraphicsCard/ServerMemory Vertex-ArrayObjectwithVBO vaods cone cube GL_ARRAY_BUFFER GL_VERTEX_ARRAY GL_COLOR_ARRAY cone GL_ARRAY_BUFFER GL_VERTEX_ARRAY GL_COLOR_ARRAY vertices[] color[] cube vbods cone cube vertices[] App/ClientMemory vertices[] color[] GraphicsCard/ServerMemory color[] vertices[] color[] Finally,UseVAOstoSwitchShapes // use, same as client-side, but cone[], ccolors[], // cube[], and bcolors[] don’t need to be in scope glBindVertexArray(vaods[CONE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, N); glBindVertexArray(vaods[CUBE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, M); glBindVertexArray(vaods[CONE]); glDrawArrays(GL_TRIANGLE_STRIP, 0, N); Seevao-vbo.cpp Next:VBOandVAOwithshaders