tags:

views:

150

answers:

4

In OpenGL, is there a way to use framebuffer data as vertex data without moving the data through the CPU? Ideally, a framebuffer object could be recast as a vertex buffer object directly on the GPU. I'd like to use the fragment shader to generate a mesh and then render that mesh.

+2  A: 

Just use the functions to do the copy and let the driver figure out how to do what you want, chances are as long as you copy directly into the vertex buffer it won't actually do a copy but will just make your VBO a reference to the data.

The main thing to be careful of is that some drivers may not like you using something you told it was for vertex data with an operation for pixel data...

Edit: probably something like the following may or may not work... (IIRC the spec says it should)

int vbo;
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, vbo);
// use appropriate pixel formats and size
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);

glEnableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
// draw stuff

Edited to correct buffer bindings thanks Phineas

Spudd86
If a stray cat is correct about GL_PIXEL_PACK_BUFFER, perhaps this should be edited.
Phineas
+2  A: 

There's a couple ways you could go about this, the first has already been mentioned by spudd86 (except you need to use GL_PIXEL_PACK_BUFFER, that's the one that's written to by glReadPixels).

The other is to use a framebuffer object and then read from its texture in your vertex shader, mapping from a vertex id (that you would have to manage) to a texture location. If this is a one-time operation though I'd go with copying it over to a PBO and then binding into GL_ARRAY_BUFFER and then just using it as a VBO.

a stray cat
So if I'm doing this every frame, then I should go with the second method (using the framebuffer as a texture in the vertex shader)? I imagine copying the framebuffer to a VBO every frame could be slow.
Phineas
This sort of thing is rather hardware dependent. It could be that the hardware is really good at copying to a PBO, or maybe the hardware doesn't have as many pipes from the texture units to the vertex shaders. The only real way to know is try both and benchmark.
a stray cat
Are you sure data does not get sent through the CPU? Does this method _guarantee_ data is fetched from memory by the GPU instead?
Etamar L.
There is no such guarantee. This is all implementation specific, but in general with modern hardware this will be done on the GPU by the driver.
a stray cat
Having tried to implement the latter approach: one caveat is that gl_FragColor gets clamped to the range [0,1], so world-space positions stored as pixels need to be range compressed.
Phineas
Actually, the ARB_color_buffer_float extension allows you to disable clamping for both fragments and glReadPixels.
Phineas
A: 

The specification for GL_pixel_buffer_object gives an example demonstrating how to render to a vertex array under "Usage Examples".

The following extensions are helpful for solving this problem:

GL_texture_float - floating point internal formats to use for the color buffer attachment GL_color_buffer_float - disable automatic clamping for fragment colors and glReadPixels GL_pixel_buffer_object - operations for transferring pixel data to buffer objects

Phineas
+1  A: 

If you can do your work in a vertex/geometry shader, you can use transform feedback to write directly into a buffer object. This also has the option of skip the rasterizer and fragment shading.

Transform feedback is available as EXT_transform_feedback or core version since GL 3.0 (and the ARB equivalent).

Matias Valdenegro