easy-gl › TransformFeedback
TransformFeedback
Captures vertex shader (or geometry shader) outputs into GPU buffers, enabling GPU-side particle simulation, geometry processing and other non-rendering compute tasks without compute shaders. Requires OpenGL 3.0+.
Setup: specify varyings
Tell OpenGL which vertex shader outputs to capture, before linking the program:
easygl::Program prog;
prog.create();
prog.attach_owned(vert);
const char* varyings[] = { "vPosition", "vVelocity" };
easygl::TransformFeedback::set_varyings(
prog.native_handle(),
{varyings, 2},
easygl::TransformFeedbackBufferMode::SeparateAttribs);
prog.link();
Interleaved vs separate attribs
| Mode | Buffers needed | Use when |
|---|---|---|
InterleavedAttribs | 1 buffer, all outputs packed | Outputs go to one struct-of-arrays |
SeparateAttribs | One buffer per varying | Outputs are independently used |
Particle simulation ping-pong
easygl::Buffer posA, posB, velA, velB;
// ... create and fill A buffers ...
easygl::TransformFeedback tf;
tf.create();
tf.bind();
// Bind output buffers
posB.bind_base(easygl::BufferTarget::TransformFeedback, 0);
velB.bind_base(easygl::BufferTarget::TransformFeedback, 1);
prog.use();
vao.bind();
device.set_rasterizer_discard_enabled(true); // no fragment stage needed
easygl::TransformFeedback::begin(easygl::PrimitiveType::Points);
device.draw_arrays(easygl::PrimitiveType::Points, 0, particleCount);
easygl::TransformFeedback::end();
device.set_rasterizer_discard_enabled(false);
// Swap A↔B for the next frame
std::swap(posA, posB);
std::swap(velA, velB);
Pause & resume
easygl::TransformFeedback::begin(easygl::PrimitiveType::Triangles);
device.draw_arrays(...);
easygl::TransformFeedback::pause();
// Intermediate draw that does NOT go into the feedback buffer
device.draw_arrays(...);
easygl::TransformFeedback::resume();
device.draw_arrays(...);
easygl::TransformFeedback::end();
Method reference
| Method | Description |
|---|---|
create() | Allocate GL transform feedback handle. |
destroy() | Free handle. Noexcept. |
bind() | Bind this transform feedback object. |
unbind() [static] | Bind feedback object 0. |
begin(primitive) [static] | Begin transform feedback recording. |
end() [static] | End recording. |
pause() [static] | Temporarily suspend recording. |
resume() [static] | Resume recording after pause. |
set_varyings(prog, varyings, mode) [static] | Specify captured varyings (must be called before link). |
is_created() | True if GL handle allocated. |
native_handle() | Raw GL integer ID. |
reset_handle_no_gl() | Context-loss recovery. |