Getting ready

Create and allocate three pairs of buffers. The first pair will be for the particle positions, the second for the particle velocities, and the third for the age of each particle. For clarity, we'll refer to the first buffer in each pair as the A buffer, and the second as the B buffer. 

Create two vertex arrays. The first vertex array should link the A position buffer with the first vertex attribute (attribute index 0), the A velocity buffer with vertex attribute one, and the A age buffer with vertex attribute two.

The second vertex array should be set up in the same way using the B buffers.  The handles to the two vertex arrays will be accessed via the GLuint array named particleArray.

Initialize the A buffers with appropriate initial values. For example, all of the positions could be set to the origin, and the velocities and start times could be initialized in the same way as described in the previous Creating a particle fountain recipe. The initial velocity buffer could simply be a copy of the velocity buffer.

When using transform feedback, we define the buffers that will receive the output data from the vertex shader by binding the buffers to the indexed binding points under the GL_TRANSFORM_FEEDBACK_BUFFER target. The index corresponds to the index of the vertex shader's output variable as defined by glTransformFeedbackVaryings.

To help simplify things, we'll make use of transform feedback objects. Use the following code to set up two transform feedback objects for each set of buffers:

GLuint feedback[2];  // Transform feedback objects 
GLuint posBuf[2];    // Position buffers (A and B) 
GLuint velBuf[2];    // Velocity buffers (A and B) 
GLuint age[2];       // Age buffers (A and B) 
 
// Create and allocate buffers A and B for posBuf, velBuf, and age

// Fill in the first age buffer
std::vector<GLfloat> tempData(nParticles);
float rate = particleLifetime / nParticles;
for( int i = 0; i < nParticles; i++ ) {
tempData[i] = rate * (i - nParticles);
}
glBindBuffer(GL_ARRAY_BUFFER, age[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, nParticles * sizeof(float),
tempData.data());
// Setup the feedback objects glGenTransformFeedbacks(2, feedback); // Transform feedback 0 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback[0]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,posBuf[0]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,1,velBuf[0]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,2,age[0]); // Transform feedback 1 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback[1]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,posBuf[1]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,1,velBuf[1]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,2,age[1]);

Similar to vertex array objects, transform feedback objects store the buffer bindings to the GL_TRANSFORM_FEEDBACK_BUFFER binding point so that they can be reset quickly at a later time. In the previous code, we create two transform feedback objects, and store their handles in the array named feedback. For the first object, we bind posBuf[0] to index 0, velBuf[0] to index 1, and startTime[0] to index 2 of the binding point (buffer set A). These bindings are connected to the shader output variables with glTransformFeedbackVaryings (or via a layout qualifier; see the following There's more... section). The last argument for each is the buffer's handle. For the second object, we do the same thing using the buffer set B. Once this is set up, we can define the set of buffers to receive the vertex shader's output, by binding to one or the other transform feedback object.

The initial values for the age buffer are all negative values. The absolute value represents how long before the particle is born. A particle is born when its age reaches zero. 

We also need some way of specifying the initial velocity of each particle. A simple solution is to use a texture of random velocities and query the texture when a random value is needed. We will use the built-in gl_VertexID variable to access a unique location within the texture for each particle. Create a 1D texture of float values and fill it with random initial velocities (the code omitted here, but is available in the example code).

The important uniform variables are as follows:

  • ParticleTex: The texture to apply to the point sprites
  • RandomTex: The texture containing the random initial velocities
  • Time: The simulation time
  • DeltaT:  Defines the elapsed time between animation frames
  • Accel: The acceleration
  • ParticleLifetime: The length of time that a particle exists before it is recycled
  • Emitter: The position of the particle emitter in world coordinates
  • EmitterBasis: A rotation matrix for directing the emitter
  • ParticleSize: The size of a particle

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.142.115