我现在正在使用计算着色器处理粒子系统。我把我所有的粒子放在一个着色器-存储-缓冲区中。粒子包含两个顶点,即当前位置和前一个位置。
struct Particle{
glm::vec4 _currPosition;
glm::vec4 _prevPosition;
};在我发送我的计算着色器之后,我想要直接从shader-storage-buffer绘制所有的粒子。这就是我要做的:
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);问题是我在屏幕上看到了_numParticles,但其中一半是用我的粒子结构的_prevPosition属性呈现的。这意味着一个粒子被解释为在屏幕上绘制的两个顶点。但我希望他跳过每个粒子结构中的_prevPosition属性。我的错误在哪里?
也许我初始化shader-storage-buffer的方式很重要:
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);
}发布于 2012-10-06 04:36:45
你的Particle结构包含两个vec4,你的compute shader为每个数组元素写两个vec4。
然而,这一行:
glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0);告诉OpenGL你正在传递一个vec4数组。你不是。您正在传递一个数组,其中每个元素都是两个vec4,并且您想跳过第二个元素。
所以告诉OpenGL,通过提供适当的步幅:
glVertexPointer(4, GL_FLOAT, sizeof(Particle), (GLvoid*)0);哦,顺便说一句:你仍然是using the wrong barrier。仅仅因为你的代码碰巧运行并不意味着它是有保证的。非同步的加载/存储操作可能很棘手,除非您做的一切都是正确的。
https://stackoverflow.com/questions/12752279
复制相似问题