3
$\begingroup$

I'm learning OpenGL compute shaders and following this guy's code, and I have stuff drawing, but not updating. The particles are spread out in their starting positions, but they stay there.

Particle manager initialization

void ParticleManager::Init(unsigned int programId,
    unsigned int computeProgramId,
    unsigned int numParticles)
{
    ...reset all particles...

    _unifLocDeltaTimeSec = glGetUniformLocation(_computeProgramId, "uDeltaTimeSec");

   _shaderBufferId = 0;
    glGenBuffers(1, &_shaderBufferId);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, _shaderBufferId);
    glBufferData(GL_SHADER_STORAGE_BUFFER, _allParticles.size() * sizeof(Particle), _allParticles.data(), GL_STATIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _shaderBufferId);  

    ...vertex array buffer and attribute array initialization...
}

Particle manager update

void ParticleManager::Update(float deltaTimeSec)
{
    glUseProgram(_computeProgramId);
    glUniform1f(_unifLocDeltaTimeSec, deltaTimeSec);

    GLuint numWorkGroupsX = (_allParticles.size() / 128) + 1;
    GLuint numWorkGroupsY = 1;
    GLuint numWorkGroupsZ = 1;
    glDispatchCompute(numWorkGroupsX, numWorkGroupsY, numWorkGroupsZ);

    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);

    glUseProgram(0);
}

Particle manager render

void ParticleManager::Render()
{
    glUseProgram(_programId);
    glBindVertexArray(_vaoId);
    glDrawArrays(GL_POINTS, 0, _allParticles.size());
    glUseProgram(0);
}

Compute shader

#version 440

struct Particle
{
    vec2 _position;
    vec2 _velocity;
    int _isActive;
};

layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;

layout (binding = 0) buffer ParticleBuffer {
    Particle AllParticles[];
};

uniform float uDeltaTimeSec;     // self-explanatory

void main()
{
    uint index = gl_GlobalInvocationID.x;
    Particle p = AllParticles[index];

    vec2 deltaPosition = p._velocity * uDeltaTimeSec;
    p._position = p._position + deltaPosition;

    AllParticles[index] = p;
}

I've looked through various forum posts (stack exchange, stack overflow, OpenGL forums) and read at least one tutorial and followed another guy's github project (only allowed 2 links in a post), but I haven't been able to figure out why nothing moves.

My top culprits are:

  1. Something in the compute shader's "delta position" is evaluating to 0.
  2. The compute shader is not getting called.
  3. The draw shader is not getting access to the compute shader's updated info.

Doubts:

  1. I hard coded a change in position, so all particles should have moved some on every frame, and when that didn't work, I hard-coded a position, and that didn't work either, so the shader might not even be getting to main().
  2. numWorkGroupsX evaluates to 79 (non-zero), so the compute shader should at least reach main().
  3. I called glMemoryBarrier(...) with GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT, so the vertex array buffer should have access to the updated info.

Also, no errors or warnings are reported during GLSL compilation or at runtime, so the computer is evidently happy with what I provided it.

Help? Why are my particles never moving beyond initialization?

$\endgroup$
  • $\begingroup$ Here is a link to the project in github. It includes all necessary 3rd party libraries and header files, so it should simply build and run after downloading. Note: This was built in VS2015 express, but I built it such that it should not need any project-specific setup. All linking is performed in the source file (should never be done for release code, but this is a barebones example program), so a non-VS2015 setup shouldn't be difficult. $\endgroup$ – John Cox Jul 30 '16 at 22:38
  • $\begingroup$ is uDeltaTimeSec none-zero? If you are drawing something then we know you are outputting _position correctly. So I would suspect some how the delta is 0 $\endgroup$ – PaulHK Jul 31 '16 at 10:25
  • $\begingroup$ @PaulHK I am sending a non-zero value by glUniform1fv, so it should be. $\endgroup$ – John Cox Aug 1 '16 at 23:42
2
$\begingroup$

Got help from someone over in the OpenGL subreddit. Apparently, as I trimmed the code for posting here and there, I changed the operation of the code.

What I trimmed to this:

void main()
{
    uint index = gl_GlobalInvocationID.x;
    Particle p = AllParticles[index];

    vec2 deltaPosition = p._velocity * uDeltaTimeSec;
    p._position = p._position + deltaPosition;

    AllParticles[index] = p;
}

Was more or less this:

void main()
{
    uint index = gl_GlobalInvocationID.x;
    Particle p = AllParticles[index];

    // update position
    vec2 deltaPosition = p._velocity * uDeltaTimeSec;
    deltaPosition = vec2(0.0f, 0.0f);
    //p._position = p._position + deltaPosition;
    p._position = deltaPosition;

    AllParticles[index] = p;
}

Which should have been this:

void main()
{
    uint index = gl_GlobalInvocationID.x;
    Particle p = AllParticles[index];

    // update position
    vec2 deltaPosition = p._velocity * uDeltaTimeSec;
    //deltaPosition = vec2(0.0f, 0.0f);
    p._position = p._position + deltaPosition;
    //p._position = deltaPosition;

    AllParticles[index] = p;
}

So I really just did that. The redditor who helped me downloaded my source code via github and found the error. Standard case of one pair of eyes glossing over an error.

All is well now.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.