Using GLSL transform feedback in OF 0.9.0

A quick note: how to set up transform feedback in OF 0.9.0 utilizing updated implementation of ofVbo and newly added ofBufferObject. This short example demonstrates how to pass an array of float numbers to the shader as Vertex Attributes via a Buffer Object and retrieve the results back to two other Buffer Objects.

C++

// Don't forget to choose appropriate OpenGL version in main.cpp - http://blog.openframeworks.cc/post/133400454159/openframeworks-090-opengl-45
ofBufferObject inputBuffer, outputBuffers[2];
ofShader shader;
ofVbo vbo;

// Load vertex shader
shader.setupShaderFromFile(GL_VERTEX_SHADER, "feedback.vert");
// Set feedback varyings before linking the shader
const GLchar* feedbackVaryings[] = { "outValue", "outValue2"};
glTransformFeedbackVaryings(shader.getProgram(), 2, feedbackVaryings, GL_SEPARATE_ATTRIBS);
// Link the shader
shader.linkProgram();

// ofBufferObjects to store input and output data
float data[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
inputBuffer.allocate();
inputBuffer.setData(sizeof(float) * 5, data, GL_DYNAMIC_DRAW);
outputBuffers[0].allocate();
outputBuffers[0].setData(sizeof(float) * 5, NULL, GL_DYNAMIC_DRAW);
outputBuffers[1].allocate();
outputBuffers[1].setData(sizeof(float) * 5, NULL, GL_DYNAMIC_DRAW);

// Set the ofBufferObject for the input data as an Vertex Attribute
vbo.setVertexBuffer(inputBuffer, 1, 0); // [in float inValue]

// Assign two other buffers to feedback varying defined in the shader
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, outputBuffers[0].getId()); // [out float outValue]
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, outputBuffers[1].getId()); // [out float outValue2]

// Render Vbo enabling transform feedback

glEnable(GL_RASTERIZER_DISCARD); // Temporary disable rendering
shader.begin();
glBeginTransformFeedback(GL_POINTS);
vbo.draw(GL_POINTS, 0, 5);
glEndTransformFeedback();
shader.end();
glDisable(GL_RASTERIZER_DISCARD);

// Read and print the results
// outputBuffer[0] (outValue) -> 1.000000 1.414214 1.732051 2.000000 2.236068
// outputBuffer[1] (outValue2) -> 2.000000 4.000000 6.000000 8.000000 10.000000

for (int i = 0; i < 2; i ++) {
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, outputBuffers[i].getId());
float feedback[5];
glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback);
printf("%f %f %f %f %f\n", feedback[0], feedback[1], feedback[2], feedback[3], feedback[4]);
}

GLSL

#version 410

in float inValue;
out float outValue;
out float outValue2;

void main() {
outValue = sqrt(inValue);
outValue2 = inValue * 2.0;
}

Not sure if this is the best way to do this in OF (let me know) but at least this satisfies my purpose of using transform feedback without disrupting other part of the rendering system of OF (which was the case when I tried in the previous version). This lets me parallelly process and update geometry data stored in Buffer Objects only within GPU, enabling complex animation to run much faster than calculating positions in CPU and uploading to GPU every frame.

vessels, pen drawing test from kynd on Vimeo.

Related Posts with Thumbnails

Leave a Reply

You must be logged in to post a comment.