OpenGL Versions in Shader Storage Buffer

I am working on a particle system using a computational shader right now. I put all my particles into the shader storage buffer. A particle contains two vertices, the current position and the previous position.

struct Particle{ glm::vec4 _currPosition; glm::vec4 _prevPosition; }; 

After I send my computational shader, I want to draw all the particles directly from the buffer storage shader. So here is what I am doing:

 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBufferID); _shaderManager->useProgram("computeProg"); glDispatchCompute((_numParticles/WORK_GROUP_SIZE)+1, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); _shaderManager->useProgram("shaderProg"); glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID); glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0); glEnableClientState(GL_VERTEX_ARRAY); glDrawArrays(GL_POINTS, 0, _numParticles); glDisableClientState(GL_VERTEX_ARRAY); 

The problem is that I see _numParticles on the screen, but one half is displayed with the _prevPosition attribute of my particle structure. This means that one particle is interpreted as two vertices that are drawn on the screen. But I want it to skip the _prevPosition attribute in every particle structure. Where is my mistake?

Perhaps the way that I initialize the storage shader buffer is important:

 GLuint shaderStorageBufferID; glGenBuffers(1, &shaderStorageBufferID); glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBufferID); glBufferData(GL_SHADER_STORAGE_BUFFER, numParticles*sizeof(Particle), NULL ,GL_STATIC_DRAW); struct Particle* particles = (struct Particle*) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, numParticles*sizeof(Particle), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); for(int i = 0; i < numParticles; ++i){ particles[i]._currPosition = glm::vec4(i, 0, 0.0, 1.0f); particles[i]._prevPosition = glm::vec4(i, 0, 1.0, 1.0f); } 
+4
source share
1 answer

Your Particle structure contains two vec4 . Your compute shader writes two vec4 elements for each element.

But this line:

 glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0); 

Tells OpenGL that you are passing an vec4 s array. You do not. You pass an array where each element is equal to two vec4 s. And you want to skip the second.

So tell OpenGL that by providing the right step:

 glVertexPointer(4, GL_FLOAT, sizeof(Particle), (GLvoid*)0); 

Oh, and BTW: you are still using the wrong barrier . Just because your code is functioning does not mean that it is guaranteed. Unsynchronized load / store operations can be difficult if you are not doing everything correctly.

+6
source

Source: https://habr.com/ru/post/1438070/


All Articles