<p>I'm trying to learn about compute shaders, and as such decided to give it a go at implementing the particle system described in these slides: <a href="https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf" rel="nofollow noreferrer">https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf</a></p>
<p>TLDR; I have an SSBO filled with particle position data:</p>
<pre><code>struct particlePos
{
    GLfloat x, y, z, w;
};
[...]
GLuint posSSBO;
glGenBuffers(1, &amp;posSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, posSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, num_particles*sizeof(particlePos),
             nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, posSSBO);
</code></pre>
<p>I dispatch a compute shader to propagate the particles, and then I wish to render each individual particle with <code>glDrawArrays(GL_POINT, 0, num_particles);</code>. Problem is, it's not working. In my humble opinion I think the slides are riddled with errors (all respect to those who wrote them as they have been very informative!). This is the code that I'm trying to get to work:</p>
<pre><code>glEnable(GL_PROGRAM_POINT_SIZE);

glBindBuffer(GL_ARRAY_BUFFER, posSSBO);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, num_particles);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
</code></pre>
<p>Granted, I'm probably doing too many things here, but I'm desperate. And it seems close to impossible to find tutorials that explain how to use compute shaders in plan English.</p>
<p>The function <code>glVertexPointer</code> seems strange and undocumented, and I read <a href="https://stackoverflow.com/questions/27017824/whats-the-purpose-of-glvertexpointer">here</a> that using attribute pointers is better. I have tried both though. This is the vertex shader:</p>
<pre><code>#version 430 compatibility

layout (location = 0) in vec4 aPosition;

layout (std140, binding = 0) buffer Pos
{
    vec4 Positions[];
};

uniform mat4 view;
uniform mat4 projection;

void main()
{
    //gl_Position = projection * view * Positions[gl_VertexID];
    //gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f); // this verified that zero shader invocations took place!
    gl_Position = aPosition;
    gl_PointSize = 50.0f; // desperate attempt!
}

</code></pre>
<p>The compute shader is a bit too long to post here in its entirety, but this is the interface:</p>
<pre><code>#version 430 compatibility
#extension GL_ARB_compute_shader :                   enable
#extension GL_ARB_shader_storage_buffer_object :     enable

layout (std140, binding = 0) buffer Pos
{
    vec4 Positions[];
};
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;

void main()
{
    uint gid = gl_GlobalInvocationID.x;   // y and z are both 1
    [...]
    Positions[gid].xyz = ... // give new position
}
</code></pre>
<p>Dispatching the compute shader is like this:</p>
<pre><code>glDispatchCompute(num_particles / work_group_size, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
</code></pre>
<p>I have checks in place that verify that particles are actually propagating. So it seems like linking the SSBO together with the vertex shader invocation is the missing piece (as well as ensuring that the compute shader is correctly written).</p>
<p>Sorry for the long question, I tried to be as specific as possible. Hopefully someone has experience with this?</p>

CC BY-SA 4.0
2022-05-12T01:03:55.650Z
"*This is the code that I'm trying to get to work:*" It's not going to. That has nothing to do with the buffer being used as an SSBO and everything to do with the code being nonsensical. You cannot simultaneously enable generic attribute 0 *and* the `gl_Vertex` attribute. You shouldn't try to combine old-style vertex attributes with generic attributes.
Nicol Bolas
CC BY-SA 4.0
2022-05-12T01:37:41.887Z
@NicolBolas As I wrote, I have tried both things - separately - and decided to post both approaches here. Neither approach worked. But maybe I need to create a separate VAO which can interpret the SSBO as if it was a vertex buffer, by setting up attribute pointers. I was trying to learn about compute shaders, but that's pretty hard when the teaching material is full of errors and/or outdated practices.
Thanks, though, for looking at my problem! :)
alexpanter
CC BY-SA 4.0
2024-05-14T11:45:15.767Z
I've been looking for answers to the same question myself. Not with particles but same principle where it counts. Did you manage to find an answer? My question is here: https://gamedev.stackexchange.com/questions/210908/is-it-possible-to-use-a-pre-existing-texture-buffer-containing-vertex-data-to-in
Iron Attorney
<opengl><compute-shader><vertex-buffer-object>
Bind shader storage buffer object for vertex input
alexpanter
# Bind shader storage buffer object for vertex input

(Asked by: username_0 on 2022-05-11)

I'm trying to learn about compute shaders, and as such decided to give it a go at implementing the particle system described in these slides: <https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf>

TLDR; I have an SSBO filled with particle position data:

```
struct particlePos
{
    GLfloat x, y, z, w;
};
[...]
GLuint posSSBO;
glGenBuffers(1, &posSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, posSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, num_particles*sizeof(particlePos),
             nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, posSSBO);

```

I dispatch a compute shader to propagate the particles, and then I wish to render each individual particle with `glDrawArrays(GL_POINT, 0, num_particles);`. Problem is, it's not working. In my humble opinion I think the slides are riddled with errors (all respect to those who wrote them as they have been very informative!). This is the code that I'm trying to get to work:

```
glEnable(GL_PROGRAM_POINT_SIZE);

glBindBuffer(GL_ARRAY_BUFFER, posSSBO);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, num_particles);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);

```

Granted, I'm probably doing too many things here, but I'm desperate. And it seems close to impossible to find tutorials that explain how to use compute shaders in plan English.

The function `glVertexPointer` seems strange and undocumented, and I read [here](https://stackoverflow.com/questions/27017824/whats-the-purpose-of-glvertexpointer) that using attribute pointers is better. I have tried both though. This is the vertex shader:

```
#version 430 compatibility

layout (location = 0) in vec4 aPosition;

layout (std140, binding = 0) buffer Pos
{
    vec4 Positions[];
};

uniform mat4 view;
uniform mat4 projection;

void main()
{
    //gl_Position = projection * view * Positions[gl_VertexID];
    //gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f); // this verified that zero shader invocations took place!
    gl_Position = aPosition;
    gl_PointSize = 50.0f; // desperate attempt!
}

```

The compute shader is a bit too long to post here in its entirety, but this is the interface:

```
#version 430 compatibility
#extension GL_ARB_compute_shader :                   enable
#extension GL_ARB_shader_storage_buffer_object :     enable

layout (std140, binding = 0) buffer Pos
{
    vec4 Positions[];
};
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;

void main()
{
    uint gid = gl_GlobalInvocationID.x;   // y and z are both 1
    [...]
    Positions[gid].xyz = ... // give new position
}

```

Dispatching the compute shader is like this:

```
glDispatchCompute(num_particles / work_group_size, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

```

I have checks in place that verify that particles are actually propagating. So it seems like linking the SSBO together with the vertex shader invocation is the missing piece (as well as ensuring that the compute shader is correctly written).

Sorry for the long question, I tried to be as specific as possible. Hopefully someone has experience with this?

**Tags:** opengl, compute-shader, vertex-buffer-object

> **Comments:**
> **username_1**: "*This is the code that I'm trying to get to work:*" It's not going to. That has nothing to do with the buffer being used as an SSBO and everything to do with the code being nonsensical. You cannot simultaneously enable generic attribute 0 *and* the `gl_Vertex` attribute. You shouldn't try to combine old-style vertex attributes with generic attributes.  
> **username_0**: @username_1 As I wrote, I have tried both things - separately - and decided to post both approaches here. Neither approach worked. But maybe I need to create a separate VAO which can interpret the SSBO as if it was a vertex buffer, by setting up attribute pointers. I was trying to learn about compute shaders, but that's pretty hard when the teaching material is full of errors and/or outdated practices. Thanks, though, for looking at my problem! :)  
> **username_2**: I've been looking for answers to the same question myself. Not with particles but same principle where it counts. Did you manage to find an answer? My question is here: https://gamedev.stackexchange.com/questions/210908/is-it-possible-to-use-a-pre-existing-texture-buffer-containing-vertex-data-to-in  

---

## 0 answers

