Particle trails using feedback transform method


#1

Hello,

I am in the process of building a particle system which at the moment is capable of calculating movements based on transform feedback method. Could anyone give some ideas on how to create a trail effect using the history of the positions?

I have 2 VAOs and 2VBOs. The VBOs contain the current and previous position values.
If I want to keep track of say 10 previous positions to create the trail effect, would I declare another VBO with 10 times the size of the VBO that contains all current positions? Or should the initial 2 VBOs be created with 10 times the size of the initial particle count? While updating the destination VBO, how would I only update the new values and push back the older positions further down the buffer? I would really appreciate it if you could give me some tips of solving this issue. Thanks and regards

The following thread talks about the same issue, but I am not sure how the indices are being saved and used to retrieve value from the buffer.

Here is a snippet of my code:

In setup():

int trailLength = 10;
particles.assign(trailLength*NUM_PARTICLES, SingleParticle()); // this is the vector of particles containing the init pos

//creating buffers
mParticleBuffer[mSourceIndex] = gl::Vbo::create(GL_ARRAY_BUFFER, particles.size() * sizeof(SingleParticle),             
    particles.data(), GL_STATIC_DRAW);
mParticleBuffer[mDestinationIndex] = gl::Vbo::create(GL_ARRAY_BUFFER, particles.size() * sizeof(SingleParticle),     
    nullptr, GL_STATIC_DRAW);

In update():

// Bind the source data (Attributes refer to specific buffers).
gl::ScopedVao source(mAttributes[mSourceIndex]);
// Bind destination as buffer base.
gl::bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mParticleBuffer[mDestinationIndex]);
gl::beginTransformFeedback(GL_POINTS);

// Draw source into destination, performing our vertex transformations.
gl::drawArrays(GL_POINTS, 0, trailLength * NUM_PARTICLES);

gl::endTransformFeedback();

#2

Hi,

Yes, this is how I did it based on the suggestions from @seph.
What would be good idea is to separate the particle attributes to individual Vbo’s. This will probably make your life easier.

mParticlePositionsBuffer[mSourceIndex] = gl::Vbo::create( GL_ARRAY_BUFFER, particles.size() * sizeof(vec4),  particlePositions.data(), GL_STATIC_DRAW );

What you also need to do is create a buffer texture that you can read old positions from in the shader.

mPositionBufferTextures[ 0 ] = gl::BufferTexture::create( mParticlePositionsBuffer[ 0 ], GL_RGBA32F );
mPositionBufferTextures[ 1 ] = gl::BufferTexture::create( mParticlePositionsBuffer[ 1 ], GL_RGBA32F );

Now it helps that you have vec4 size positions only in the Vbo.
You also need to store the id of the particle, you can do it in the w part of the vec4.

To update you do something like this in your transform feedback shader:

const int kTrailSize = 10;

layout (location = 0) in vec4 iPosition;

uniform samplerBuffer uTexPositions;

out vec4 oPosition;

void main()
{
    int id = int( iPosition.w );
    if ( ( id % kTrailSize ) == 0 )
    {
        // head of trail, update as you would do it without trails
    }
    else
    {
        // part of trail, copy previous position
        oPosition = texelFetch( uTexPositions, id - 1 );
        oPosition.w = iPosition.w;
    }
}

#3

Instead of casting a float to an int, you might want to use floatBitsToInt and intBitsToFloat for that.


#4

Thank you @gabor_papp for the helpful description. I really appreciate it. I will give this a shot and see how things look.
And thank you @paul.houx for the suggestion. Cheers!


#5

Hey, just wanted to share some experiments I did with GPU based ribbons using transform feedbacks. There is not a lot info online and I only found some talk about xfb ribbons on this forum. I’m experimenting with ribbons using an index buffer to select the positions that make up the ribbons. For now just 2D, but it shows one approach you can take: https://bitbucket.org/roxlu/2018-002-gpu-ribbons


Transform feedback particle trails
#6

So how would one approach a compute shader method? I hear it’s pretty grand. I admit, I’m freshly new to compute shaders. However, using avseol’s ssbo example for example

Would it just be a matter of adding a massive ssbo or vbo that would hold the FLOCK_SIZE*TRAILSIZE positions and trail ID?
I was thinking, since we are only updating the newest position on the trail, perhaps we can just copy the vbo positions into a larger vbo at a specific offset in the main app.
I was digging around and came across CopyBufferSubData. Theres not really a ton out there on this flocking trails subject but I did also come across this massive hlsl Unity code which would be cool to implement some of the ideas but I’m having a hard time figuring out the overall technique in the main app.
I even looked into texture3D since most every resource refers to smaller particle systems that use textures but figured I’d get some opinions.