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

ModeBuffers neededUse when
InterleavedAttribs1 buffer, all outputs packedOutputs go to one struct-of-arrays
SeparateAttribsOne buffer per varyingOutputs 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

MethodDescription
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.