Setting additional attributes for transform feedback

I’m trying to use an additional attribute in a transform feedback shader, and I just can’t get it to work. The idea is to create particle trails- I pass in a position and texture holding the previous values. The positions are being updated by a simple rotation matrix that changes over time. I need to pass in the original position of the particle as well as the previous positions in the texture.

If the vertex is at the head of the trail, I update it’s position using the new value of the matrix; if it’s further down the trail, I use the previous position that has been passed in.

The attribute I’m trying to set is called position, and I’m setting it with the contents of feedbackSourceBuffer below.

// particleGen is creating a list of vec4s to use as positions
// transformManager is (currently) just updating a rotation matrix

void ofApp::setupTrails() {

  int i, j;

  // Feedback settings
  feedbackSettings.shaderFiles[GL_VERTEX_SHADER] = "shaders/transformShader.vert";
  feedbackSettings.bindDefaults = true;
  feedbackSettings.varyingsToCapture = { "outputVec" };
  feedbackShader.setup(feedbackSettings);

  numTrails = particleGen.numParticles;
  
  // Allocate the buffers to use
  feedbackSourceBuffer.allocate(sizeof(glm::vec4) * numTrails * pointsPerTrail, GL_STATIC_DRAW);
  feedbackBuffer1.allocate(sizeof(glm::vec4) * numTrails * pointsPerTrail, GL_DYNAMIC_DRAW);
  feedbackBuffer2.allocate(sizeof(glm::vec4) * numTrails * pointsPerTrail, GL_DYNAMIC_DRAW);
  
  // Create some pointers to make flip-flop easier
  fromBuffer = &feedbackBuffer1;
  toBuffer = &feedbackBuffer2;

  std::vector<float> init;
  std::vector<int> indices;
  
  // These are the indices of the trails. There's extra being added because I'm using line strips with 
  // primitive restart at a particular index
  trailIndexBuffer.allocate(sizeof(int) * (numTrails * pointsPerTrail + numTrails), GL_STATIC_DRAW);

  // Set the initial values from those generated in the particleGen
  for (i = 0; i < numTrails; i++) {

    for (j = 0; j < pointsPerTrail; j++) {
      init.insert(init.end(), { 
        particleGen.particleValues[i * 4],
        particleGen.particleValues[i * 4 + 1],
        particleGen.particleValues[i * 4 + 2],
        particleGen.particleValues[i * 4 + 3]
      });

      indices.insert(indices.end(), i * pointsPerTrail + j);
    }

    indices.insert(indices.end(), restartIndex);
  }

  // Set the data in the buffers
  feedbackSourceBuffer.setData(init, GL_DYNAMIC_DRAW);
  feedbackSourceBuffer.copyTo(*toBuffer);
  feedbackSourceBuffer.copyTo(*fromBuffer);

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // !!!! If I do this, I end up with a blank screen, as if nothing has been processed
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  //trailsVbo.setVertexBuffer(feedbackSourceBuffer);
  
  trailsVbo.setVertexBuffer(*toBuffer, 4, 0, 0); 
  
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // !!!! For some reason I can't use this attribute?
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  
  trailsVbo.setAttributeBuffer(feedbackShader.getAttributeLocation("position"), feedbackSourceBuffer, 4, sizeof(glm::vec4));
  
  trailsVbo.enableIndices();
  trailIndexBuffer.setData(indices, GL_STATIC_DRAW);
  trailsVbo.setIndexBuffer(trailIndexBuffer);
  
  // Run feedback a few times to set the initial trails up
  for (i = 0; i < pointsPerTrail; i++) {
    transformManager.update(timeStepf * i);
    doFeedback();
  }

}

void ofApp::doFeedback() {
  // Reallocate the texture that gets read in
  feedbackTexture.allocateAsBufferTexture(*fromBuffer, GL_RGBA32F);
  
  
  feedbackShader.beginTransformFeedback(GL_POINTS, *toBuffer);
  feedbackShader.setUniformMatrix4f("modelMatrix", transformManager.matrix);
  feedbackShader.setUniformTexture("tex", feedbackTexture, 0);
  feedbackShader.setUniform1i("trailSize", pointsPerTrail);

  trailsVbo.draw(GL_POINTS, 0, numTrails * pointsPerTrail);
  feedbackShader.endTransformFeedback(*toBuffer);

  // Swap the buffers over
  ofBufferObject* tmp = fromBuffer;
  fromBuffer = toBuffer;
  toBuffer = tmp;
    
}

and then in the shader…

#version 330
uniform int trailSize;
uniform samplerBuffer tex;
uniform mat4 modelMatrix;

in vec4 position;
out vec4 outputVec;

void main() {
  
  int id = gl_VertexID;
  outputVec = position; 

  if (id % trailSize == 0) {
    outputVec = texelFetch(tex, id) * position; // this just displays blank
    outputVec = texelFetch(tex, id) * modelMatrix; // this works fine, but isn't right - if I keep updating the model matrix, this explodes
  }
  else {
    outputVec = texelFetch(tex, id - 1);
  }

}

Can anyone see what I’m doing wrong here? Thanks in advance!