Transform feedback works the first frame, but not after that.
This is particle system based on "GLSL Cookbook" example, though I'm converting it to OpenGL 3.3.
My program set up:
I have two sets of vertex array buffers for each attribute (2 for position, 2 for velocity, 2 for startTime). 2 VAOs, the first corresponding to the first set up buffers, and the second VAO corresponding the second set of buffers. The VAO sets up the vertex attributes to the for the corresponding buffers.
There are two shader programs, the first performs the transform feedback, the second one renders.
On each frame the transform feedback is performed first with the transform feedback shader program and a VAO, then the render shader with the other VAO renders. On each successive frame the VAOs are swapped.
If I use a query with GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
I can see that only the first time all the primitives are written, after that the primitives written value is 0
. Also I can visually see the first pass worked by seeing points flicker on screen (flicker between the start location of the points and the location they were transformed in the first frame).
I am seeing this problem on Mac OS X only (it works perfectly on Linux and Windows). I know Mac is a little behind with some OpenGL functionality but I cannot find anything that indicates that would be an issue in this case.
Also I checked for OpenGL errors while rendering and there were none.
Before linking the transform feedback shader:
const char * outputNames[] = { "position", "velocity", "startTime" };
glTransformFeedbackVaryings(
m_transformShader.programId(),
3,
outputNames,
GL_SEPARATE_ATTRIBS);
Here is the render function code I am using:
// ************** Transform feedback pass
m_transformShader.bind();
glEnable(GL_RASTERIZER_DISCARD);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, positionBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, velocityBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, startTimeBuffer[drawBuf]);
m_vao[1-m_drawBuf].bind();
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, numParticles);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
// ************** Render pass
m_renderShader.bind();
glClear( GL_COLOR_BUFFER_BIT );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
m_renderShader.setUniformValue("texSampler", 0);
m_vao[m_drawBuf].bind();
glDrawArrays(GL_POINTS, 0, numParticles);
m_vao[m_drawBuf].release();
m_renderShader.release();
m_drawBuf = 1 - m_drawBuf;
Vertex Shader for transform feedback shader (m_transformShader
):
#version 330
layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec3 vertexVelocity;
layout (location = 2) in float vertexStartTime;
layout (location = 3) in vec3 vertexInitialVelocity;
out vec3 position;
out vec3 velocity;
out float startTime;
uniform float time;
uniform float H;
uniform vec3 accel;
uniform float lifespan;
void main()
{
position = vertexPosition;
velocity = vertexVelocity;
startTime = vertexStartTime;
if ( time >= startTime )
{
float age = time - startTime;
if ( age > lifespan )
{
position = vec3(0.0);
velocity = vertexInitialVelocity;
startTime = time;
}
else
{
position += velocity * H;
velocity += accel * H;
}
}
}
Rendering vertex shader:
#version 330
layout (location = 0) in vec3 vPosition;
layout (location = 2) in float vStartTime;
out float alpha;
uniform mat4 MVP;
uniform float time;
uniform float lifespan;
void main()
{
gl_PointSize = 10.0;
float age = time - vStartTime;
alpha = 1.0 - age / lifespan;
gl_Position = MVP * vec4(vPosition, 1.0);
}
I am using OpenGL 3.3 context.