Open GL : Storing Transformed Vertices—Transform Feedback (part 2)

10/17/2012 4:18:38 AM

Turning Off Rasterization

So far, you have seen that transform feedback is a mechanism to save the intermediate results of vertex or geometry shaders while OpenGL is rendering. But, what if you don’t want to actually draw anything? What if you only want to use transform feedback on its own without changing the contents of the screen? This is the kind of thing you may want to do if you’re using the vertex shader for computation other than geometry processing (physical simulation, for example). It is possible to use transform feedback for this purpose by turning off rasterization. This means that the vertex and geometry shaders will still run so that transform feedback will work, but the OpenGL pipeline will be chopped off after that and the fragment shader will not run at all. This is therefore more efficient than simply making a fragment shader that discards everything, or turning off color writes with glColorMask, for example. To turn off rasterization, you actually need tell to OpenGL that it should discard all rasterization by calling


To turn rasterization back on, simply call


When GL_RASTERIZER_DISCARD is enabled, anything produced by the vertex or geometry shader (if present) does not create any fragments, and the fragment shader never runs. If you turn off rasterization and do not use transform feedback mode, the OpenGL pipeline is essentially turned off.

Counting Vertices Using Primitive Queries

When a vertex shader but no geometry shader is present, the output from the vertex shader is recorded, and the number of vertices stored into the transform feedback is the same as the number of vertices sent to OpenGL unless the available space in any of the transform feedback buffers is exhausted. If a geometry shader is present, that shader may create or discard vertices and so the number of vertices written to the transform feedback buffer may be different than the number of vertices sent to OpenGL. OpenGL can keep track of the number of vertices written to the transform feedback buffers through query objects. The application can then use this information to draw the resulting data or to know how much to read back from the transform feedback buffer, should it want to keep the data.

As before, to generate a query object, call

glGenQueries(1, &one_query);

or to generate a number of query objects, call

glGenQueries(10, ten_queries);

Now that you have created your query objects, you can ask OpenGL to start counting primitives as it produces them by beginning a GL_PRIMITIVES_GENERATED or GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query by beginning the query of the appropriate type. To start either query, call

glBeginQuery(GL_PRIMITIVES_GENERATED, one_query);



After a call to glBeginQuery with either GL_PRIMITIVES_GENERATED or GL_TRANSFORM_FEEDBACK_PRIMTIVES_WRITTEN, OpenGL keeps track of how many primitives were produced by the vertex or geometry shader, or how many were actually written into the transform feedback buffers until the query is ended using




The results of the query can be read by calling glGetQueryObjectuiv with the GL_QUERY_RESULT parameter and the name of the query object. As with other OpenGL queries, the result might not be available immediately because of the pipelined nature of OpenGL. To find out if the results are available, call glGetQueryObjectuiv with the GL_QUERY_RESULT_AVAILABLE parameter. 

There are a couple of subtle differences between the GL_PRIMITIVES_GENERATED and GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. The first is that the GL_PRIMITIVES_GENERATED query counts the number of primitives emitted by the geometry shader, but the GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query only counts primitives that were successfully written into the transform feedback buffers. The primitive count generated by the geometry shader may be more or less than the number of primitives sent to OpenGL, depending on what it does. Normally, the results of these two queries would be the same, but if not enough space is available in the transform feedback buffers, GL_PRIMITIVES_GENERATED will keep counting, but GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN will stop.

You can check whether all of the primitives produced by your application were captured into the transform feedback buffer by running one of each query simultaneously and comparing the results. If they are equal, then all the primitives were successfully written. If they differ, the buffers you used for transform feedback were probably too small.

The second difference is that GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN is only meaningful when transform feedback is active. That is why it has TRANSFORM_FEEDBACK in its name but GL_PRIMITIVES_GENERATED does not. If you run a GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query when transform feedback is not active, the result will be zero. However, the GL_PRIMITIVES_GENERATED query can be used at any time and will produce a meaningful count of the number of primitives produced by OpenGL. You can use this to find out how many vertices your geometry shader produced or discarded.

Using the Results of a Primitive Query

Now you have the results of your vertex or geometry shader stored in a buffer. You also know how much data is in that buffer by using a query object. Now it’s time to use those results in further rendering. Remember that the results of the vertex or geometry shader are placed into a buffer using transform feedback. The only thing making the buffer a transform feedback buffer is that it’s bound to one of the GL_TRANSFORM_FEEDBACK_BUFFER binding points. However, buffers in OpenGL are generic chunks of data and can be used for other purposes.

Generally, after running a rendering pass that produces data into a transform feedback buffer, you bind the buffer object to the GL_ARRAY_BUFFER binding point so that it can be used as a vertex buffer. If you are using a geometry shader that might produce an unknown amount of data, you need to use a GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query to figure out how many vertices to render on the second pass. Listing 1 shows an example of what such code might look like.

Listing 1. Drawing Data Written to a Transform Feedback Buffer
// We have two buffers, buffer1 and buffer2. First, we'll bind buffer1 as the
// source of data for the draw operation (GL_ARRAY_BUFFER), and buffer2 as
// the destination for transform feedback (GL_TRANSFORM_FEEDBACK_BUFFER).
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
// Now, we need to start a query to count how many vertices get written to
// the transform feedback buffer
// Ok, start transform feedback...
// Draw something to get data into the transform feedback buffer
// Done with transform feedback
// End the query and get the result back
glGetQueryObjectuiv(q, GL_QUERY_RESULT, &vertices_to_render);
// Now we bind buffer2 (which has just been used as a transform
// feedback buffer) as a vertex buffer and render some more points
// from it.
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glDrawArrays(GL_POINTS, 0, vertices_to_render);


Most View
Iphone SDK : Working with the Address Book Database - Accessing Multi-Value Properties
ZyXEL PL4201 Powerline Adaptor
Scan 3XS Sniper FT03 Nanu - Compact Gaming Systems
Dragon Dictate For Mac 3
Intel SSD 310 40GB - A Sophisticated Nightmare
ASUS Orion Pro Gaming Headset - Jack of both trades
Brother HL-5450DN - Built For Speed
New Products For May (Part 1)
Hot Gadgets – March 2013 (Part 2)
Group Test: Sub-8in Tablets (Part 2) : Apple iPad Mini, Barnes & Noble Nook HD, Fuhu Nabi 2
Top 10
Show Report Special Americana International
Show Report Special Stars & Stripes
Star Project 190SL Roadster (Part 2)
Star Project 190SL Roadster (Part 1)
Still The One - The Mclaren F1 (Part 2)
Still The One - The Mclaren F1 (Part 1)
The Maserati Ghibli S – The Latin Conquistador (Part 2)
The Maserati Ghibli S – The Latin Conquistador (Part 1)
The Lexus CT200h F-Sport – A Good Deal Easier To Live With
The Mercedes-Benz C-Class Estate – A Practical And Comfortable Choice Of Family Car