[MacRuby-devel] Vertex buffer objects in OpenGL
Dave Baldwin
dave.baldwin at dsl.pipex.com
Wed Jan 12 13:29:55 PST 2011
Just to give an answer for anyone finding this later.
On 21 Dec 2010, at 20:20, Dave Baldwin wrote:
> I have an openGL program that works if I use vertex arrays to store the geometry data, but if I convert it to use an openGL vertex buffer object then nothing is drawn. Has anyone got vertex buffer objects to work with MacRuby? I am using 0.8 on 10.6.4
>
> (In OpenGL a vertex buffer object just holds geometry but on the graphics card so for large amounts of geometry will be significantly faster than a vertex array where the geometry is held in the client's memory and copied to the graphics card every time it is drawn).
>
> The code is:
>
> @vbo_buffer = Pointer.new('f', 1000)
> ... # initialise with vertex data (BYTES_IN_BUFFER set up with the size of the vertex data)
>
> # Get a buffer object id
> cubeVBO = Pointer.new_with_type('I', 1)
> glGenBuffers(1, cubeVBO)
> @cubeVBO = cubeVBO[0]
>
> glBindBuffer(GL_ARRAY_BUFFER, @cubeVBO)
>
> # The vertex buffer object can be initialised in several ways
> case vbo_method
> when :writeOnAllocate
> # This call will allocate the vertex buffer object and initialise it from @vbo_buffer
> glBufferData(GL_ARRAY_BUFFER, BYTES_IN_BUFFER, @vbo_buffer, GL_STATIC_DRAW)
> when :writeAfterAllocate
> nullPtr = Pointer.new("^I")
> # This call will allocate the vertex buffer object but not initialise it.
> glBufferData(GL_ARRAY_BUFFER, BYTES_IN_BUFFER, nullPtr, GL_STATIC_DRAW)
> # Now initialise it.
> glBufferSubData(GL_ARRAY_BUFFER, 0, BYTES_IN_BUFFER, @vbo_buffer)
> when :mapAfterAllocate
> nullPtr = Pointer.new("^I")
> # This call will allocate the vertex buffer object but not initialise it.
> glBufferData(GL_ARRAY_BUFFER, BYTES_IN_BUFFER, nullPtr, GL_STATIC_DRAW)
> # Get a pointer to the allocated buffer and copy the data over manually.
> buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE).cast!('f')
> (BYTES_IN_BUFFER / 4).times {|i| buffer[i] = @vbo_buffer[i]} # copy as floats
> glUnmapBuffer(GL_ARRAY_BUFFER)
> end
>
> Finally to draw the vertex buffer object
>
> glBindBuffer(GL_ARRAY_BUFFER, @cubeVBO)
>
> glEnableClientState(GL_VERTEX_ARRAY)
>
> v = Pointer.new("^c") # gives us a null pointer - need to pass in 0 in next call
> glVertexPointer(3, GL_FLOAT, v)
>
> glColor3f(1.0, 0.0, 0.0)
> glDrawArrays(GL_QUADS, 0, 24) # 0 = start offset, 24 = number of vertices
>
>
> None of the three methods to load the vertex buffer object make a difference. The other problem I will have is the colour data is interleaved in with the vertex data so ideally I need to call:
> glVertexPointer(3, GL_FLOAT, 12)
> but this function needs to take a void* pointer so how do I create a pointer with a value?
>
> Dave.
All the methods for loading the in vertex data work fine and the only problem (as alluded to) is how to pass an integer to a C function expecting a void * pointer.
There is no way to do this in MacRuby 0.8 and the only option is to write a small objective C stub to do this. One such stub looks like:
- (void) glVBOVertexPointer: (GLint) size type: (GLenum) type stride: (GLsizei) stride offset:(GLint) offset
{
glVertexPointer(size, type, stride, (void *) offset);
}
and once you have built this and loaded it (see http://www.macruby.org/recipes/create-an-objective-c-bundle.html) then calling it
glVBOVertexPointer(3, type: GL_FLOAT, stride: strideInBytesBetweenVertices, offset: 0)
make everything work as expected.
Dave.
More information about the MacRuby-devel
mailing list