I'm new to the forums, so short introduction? Hi.Next on the agenda, I'd like to clear out that I have been programming for years, but I have very little experience with OpenGL. I started a project a few days ago and was hoping that a kind spirit would make a complete step-by-step tutorial for VBO's. I have looked up documentation and "tutorials," but with little luck.As for as the OpenGL progress goes I have a packed vertex array and an index array. I already have the project setup in Eclipse. Help greatly appreciated! ~Braindrool P.s. I frequently check email, if you need any more information please do ask |
Administrator
|
Hi
I used these classes (still based on JOGL 1) to handle vertex arrays and VBOs: http://tuer.svn.sourceforge.net/viewvc/tuer/alpha/drawer/VertexArray.java?revision=123&content-type=text%2Fplain http://tuer.svn.sourceforge.net/viewvc/tuer/alpha/drawer/DynamicVertexBufferObject.java?revision=123&content-type=text%2Fplain Just look at the key differences. When you create a VBO, you need to call glGenBuffers (to create the identifier), glBindBuffer (to bind the current buffer) and glBufferData (to associate the data store on the GPU to a buffer on the CPU if any and to set the "update" mode). This "update" mode can be ignored by the driver, it is an hint, it changes nothing under very early implementations of VBO whereas it can be very efficient on recent graphics cards. Call glBindBuffer when you want to use a VBO just before drawing. Sometimes you might have to call glBindBuffer with 0 to unbind a buffer. Good luck.
Julien Gouesse | Personal blog | Website
|
Administrator
|
In reply to this post by Braindrool
I have a VBO tutorial at http://wadeawalker.wordpress.com/2010/10/17/tutorial-faster-rendering-with-vertex-buffer-objects/ that might be helpful.
|
Looks useful. But a few questions stand.
//================================================================ /** * Creates vertex buffer object used to store vertices and colors * (if it doesn't exist). Fills the object with the latest * vertices and colors from the data store. * * @param gl2 GL object used to access all GL functions. * @return the number of vertices in each of the buffers. */ protected int [] createAndFillVertexBuffer( GL2 gl2, List<DataObject> listDataObjects ) { int [] aiNumOfVertices = new int [] {listDataObjects.size() * 4}; // create vertex buffer object if needed if( aiVertexBufferIndices[0] == -1 ) { // check for VBO support if( !gl2.isFunctionAvailable( "glGenBuffers" ) || !gl2.isFunctionAvailable( "glBindBuffer" ) || !gl2.isFunctionAvailable( "glBufferData" ) || !gl2.isFunctionAvailable( "glDeleteBuffers" ) ) { Activator.openError( "Error", "Vertex buffer objects not supported." ); } gl2.glGenBuffers( 1, aiVertexBufferIndices, 0 ); // create vertex buffer data store without initial copy gl2.glBindBuffer( GL.GL_ARRAY_BUFFER, aiVertexBufferIndices[0] ); gl2.glBufferData( GL.GL_ARRAY_BUFFER, aiNumOfVertices[0] * 3 * Buffers.SIZEOF_FLOAT * 2, null, GL2.GL_DYNAMIC_DRAW ); } // map the buffer and write vertex and color data directly into it gl2.glBindBuffer( GL.GL_ARRAY_BUFFER, aiVertexBufferIndices[0] ); ByteBuffer bytebuffer = gl2.glMapBuffer( GL.GL_ARRAY_BUFFER, GL2.GL_WRITE_ONLY ); FloatBuffer floatbuffer = bytebuffer.order( ByteOrder.nativeOrder() ).asFloatBuffer(); for( DataObject dataobject : listDataObjects ) storeVerticesAndColors( floatbuffer, dataobject ); gl2.glUnmapBuffer( GL.GL_ARRAY_BUFFER ); return( aiNumOfVertices ); } 1. listDataObjects is just the vertex data? 2. aiVertexBufferIndices is? 3. Could you do the traditional Byte / FloatBuffer as in X = Bytebuffer.allocateDirect( size ).asFloatBuffer().order(Buffer.nativeOrder())? Or however that goes. |
Administrator
|
1. Oops, I missed a @param when I wrote this :) Yes, listDataObjects is just a list of class instances, each of which is a colored quad in my case. A DataObject is just meant to represent some object in the host application that needs to be drawn. storeVerticesAndColors() is responsible for turning such an object into vertex and color data and putting it in the VBO. Normally apps copy their data into the VBO when it's time to draw, instead of just maintaining it there always (because VBO memory is allocated and managed by the OpenGL kernel driver). 2. There's should be comment for aiVertexBufferIndices at the top of the file. It's the array of integer VBO indices returned by gl2.glGenBuffers(). 3. I don't think so. The VBO must be allocated by OpenGL, then you put data into it by "mapping" a FloatBuffer over it as shown. If you call Bytebuffer.allocateDirect() as you showed, you're allocating the memory yourself, it's not being managed by the OpenGL driver, so its contents are unknown to OpenGL. |
2. What if you already have an array of indices?
|
Administrator
|
You might be thinking of a different kind of indices :) These "indices" are essentially just the names of VBOs created by the OpenGL driver (like file handles). This example uses a vertex buffer, but not an index buffer, so there are no primitive indices that map primitives onto vertices in the buffer -- the glDrawArrays() call just assumes an index buffer of the form {0, 1, 2, 3, 4, 5, ... }.
|
This might sound a bit greedy, but do you think you could just write a short, working example from my code?
The basics of course: package com.braindrool.game; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; public class Renderer implements GLEventListener { public void display(GLAutoDrawable drawable) { } public void dispose(GLAutoDrawable arg0) { } public void init(GLAutoDrawable drawable) { } public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) { } } I already have a .ply model loader / scanner / transformer. E.g. model.load("models/monkey.ply") will return a FloatBuffer of the packed Vertices from file. But if you do decide to do this (which I very much hope you do ^^), would you please put in detail step-by-step what you're doing? I'd prefer to have all my questions answered in one response, but everyone knows a panacea doesn't exist :P |
Administrator
|
Dude, for reals? Seriously, the only way to learn that stuff is just dig in and start writing it -- if I write it for you, you'll never get any better at it Just start from a working tutorial (mine or someone else's), then just hack your code into it a bit at a time. That way you've always got something that works, and you can't get too far off the track. Good luck! |
Meh, I suppose you are right. I believe this will be my final question though!
ByteBuffer bytebuffer = gl.glMapBuffer( GL.GL_ARRAY_BUFFER, GL2.GL_WRITE_ONLY ); FloatBuffer floatbuffer = bytebuffer.order( ByteOrder.nativeOrder() ).asFloatBuffer(); Mind elaborating on glMapBuffer a bit? I see several C tutorials. Another question would be, how would I just use my FloatBuffer parameter? It would be more convenient for me. And to make sure I have this understood correctly. Use an int to create a VBO handle, generate VBO, allocate space, map data, return the VBO handle as a drawing object. Yes? |
Administrator
|
glMapBuffer() is needed because to write to a VBO using the CPU, the VBO must be in system memory, but to render a VBO with your GPU, the VBO must be in your graphics card's memory. On a desktop PC, those two memories are physically separate, and the only communication between them is via the PCI bus. So (naively speaking) glMapBuffer() copies the VBO from graphics card memory into system memory, then returns a pointer to it that the CPU can use (the pointer is inside the returned ByteBuffer). Then bytebuffer.order( ByteOrder.nativeOrder() ).asFloatBuffer() re-wraps that pointer so you can write floats to it from Java. Finally glUnmapBuffer() flushes the system-memory copy of the VBO back out to graphics card memory so the GPU can render it. This picture may be a bit more complex in reality, since the OpenGL driver can try to optimize memory traffic over the PCI bus by not copying data that hasn't changed (so it may not copy the VBO back from the graphics card, it may just keep a local copy). The driver can also batch up bus operations, so they may not happen right when you make the OpenGL calls. And finally, on a mobile platform like a cell phone or tablet, the system and GPU memories are not physically separate, so there's no bus flushing at all, though the driver may still have to keep CPU and GPU data in separate address spaces. glGenBuffers() - create VBO "handle" (really just an integer index to some driver-maintained list of VBOs) glBufferData() - "allocates space" (exactly where and how is left up to the OpenGL driver) glMapBuffer() - get system pointer to VBO glUnmapBuffer() - flush VBO changes out to graphics card plus: glBindBuffer() - tells OpenGL which VBO subsequent OpenGL calls will refer to All these calls are documented in detail at http://www.opengl.org/, though not in a very beginner-friendly form. |
You have my thanks for helping me. I successfully created a VBO renderer. Would have helped though if I knew the model I was using was bugged.
http://imgur.com/dG8Fz |
Administrator
|
You're welcome! I'm glad things are working now.
|
You seem plenty experienced with JOGL so far, so thought I might notify you of my most recent post. http://forum.jogamp.org/Loading-attributes-in-a-packed-buffer-td4027450.html
I would greatly appreciated more help! |
Did you manage to get things working, Brain? I'm kind of going through the same stuff myself. I want to learn an efficient way to create VBOs so I can move beyond "immediate mode" OpenGL... >_>
|
Administrator
|
I already gave several examples, there is one using interleaved arrays in my source code.
Julien Gouesse | Personal blog | Website
|
In reply to this post by sunnystormy
Found an easy way for OpenGL, not OpenGLES. But yes, I got it to work.
On Tue, Mar 5, 2013 at 3:53 PM, sunnystormy [via jogamp] <[hidden email]> wrote: Did you manage to get things working, Brain? I'm kind of going through the same stuff myself. I want to learn an efficient way to create VBOs so I can move beyond "immediate mode" OpenGL. : P |
Free forum by Nabble | Edit this page |