Transform feedback in OF 0.9.0 – looping feedback

December 27th, 2015

Following up with the last post answering the question I was asked several times – to keep updating the same attribute, e.g. vertex positions with transform feedback, you can use ping-pong technique to create a sort of feedback loop. Prepare two Buffer Objects, or ofBufferObjects for each shader attribute you want to update with feedback transform, then swap them every frame so that the updated buffer becomes the next input while the other becomes the next receiver of the output.

See the code snippets below. The complete example is on GitHub.

.h file
int currentAttributeBuffer = 0;
ofBufferObject positionBuffers[2];

.cpp
int feedbackTargetBuffer = 1 - currentAttributeBuffer;
vbo.setVertexBuffer(positionBuffers[currentAttributeBuffer], 4, 0); // Set one of the ofBufferObject as an attribute for the vertex shader
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, positionBuffers[feedbackTargetBuffer].getId()); // Set the other ofBuffer as the target of the transform feedback
currentAttributeBuffer = feedbackTargetBuffer;

Using GLSL transform feedback in OF 0.9.0

December 26th, 2015

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.

Explosive mutant lily

January 24th, 2015

And more WIP screenshots.

[BRDG020] Lilium from BRDG on Vimeo.

Fullscreen + headphones are highly recommended to indulge in the violent yet delicate sound piece by Yaporigami.

141012_06
141002_02
141012_01
140928_02
140922_04
140921_03
140914_10
140914_07
140914_05
140912_02
140907_01
140831_11
140831_10
140831_04
140830_09
140830_02

More

Quaternion for Processing

August 19th, 2014

I (and @robbietilton) just needed so I wrote a simple quaternion class that comes in handy when recursively rotating PVectors. The detailed documentation is on GitHub.

GitHub
Download


// usage examples

PVector v = new PVector(1,0,0);
Quaternion q = new Quaternion(radians(30), new PVector(0,0,1)); // rotate 30 degrees around z-axis
v = q.mult(v); // apply rotation to the vector


PVector v2 = new PVector(0,1,0);
Quaternion xRot = new Quaternion(radians(30), new PVector(1,0,0)); // rotate 30 degrees around x-axis
Quaternion yRot = new Quaternion(radians(30), new PVector(0,1,0)); // rotate 30 degrees around y-axis
v2 = xRot.mult(yRot).mult(v2); // apply two rotations to the vector

Related Posts with Thumbnails