In the vertex shader, we have code that supports two passes: the update pass where the particles' position, age, and velocity are updated, and the render pass where the particles are drawn:
const float PI = 3.14159265359;layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexVelocity;layout (location = 2) in float VertexAge;// Render passuniform int Pass;// Output to transform feedback buffers (pass 1)out vec3 Position;out vec3 Velocity;out float Age;// Out to fragment shader (pass 2)out float Transp; // Transparencyout vec2 TexCoord; // Texture coordinate // Uniform variables here... (omitted)vec3 randomInitialVelocity() { // Access the texture containing random velocities using gl_VertexID...}