C++ 着色器存储缓冲区中的OpenGL顶点

C++ 着色器存储缓冲区中的OpenGL顶点,c++,opengl,C++,Opengl,我现在正在使用计算着色器处理粒子系统。我将所有粒子放入着色器存储缓冲区。粒子包含两个顶点,即当前位置和上一个位置 struct Particle{ glm::vec4 _currPosition; glm::vec4 _prevPosition; }; 在分派计算着色器之后,我希望直接从着色器存储缓冲区绘制所有粒子。我就是这么做的: glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBufferID);

我现在正在使用计算着色器处理粒子系统。我将所有粒子放入着色器存储缓冲区。粒子包含两个顶点,即当前位置和上一个位置

struct Particle{
    glm::vec4   _currPosition;
    glm::vec4   _prevPosition;
};
在分派计算着色器之后,我希望直接从着色器存储缓冲区绘制所有粒子。我就是这么做的:

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属性。我的错在哪里

可能我初始化着色器存储缓冲区的方式很重要:

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);
}
GLuint着色器存储缓冲ID;
glGenBuffers(1,&shaderStorageBufferID);
glBindBuffer(GL_着色器_存储_缓冲区,shaderStorageBufferID);
glBufferData(GL_着色器_存储_缓冲区,numParticles*sizeof(粒子),NULL,GL_静态_绘制);
结构粒子*粒子=(结构粒子*)glMapBufferRange(GL_着色器\存储\缓冲区,0,numParticles*大小(粒子),GL_贴图\写入\位| GL_贴图\无效\缓冲区\位);
对于(int i=0;i
您的
粒子
结构包含两个
vec4
。每个数组元素写入两个
vec4
s

但这一行:

glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0);
告诉OpenGL您正在传递一个
vec4
s数组。你不是。您正在传递一个数组,其中每个元素都是两个
vec4
s。你想跳过第二个

因此,告诉OpenGL,通过提供适当的步幅:

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

哦,顺便说一句:你还是。仅仅因为你的代码恰好是函数,并不意味着它是有保证的。非同步加载/存储操作可能会很棘手,除非您能正确地完成所有操作。

您的代码是现代OpenGL和传统OpenGL的惊人集合。你怎么会有足够的能力来使用计算着色器,并且对内存同步问题有一定的了解(顺便说一句,你仍然使用了错误的屏障。仅仅因为你的代码碰巧起作用并不意味着它一定会起作用),但是你使用了一个过时的函数,比如
glVertexPointer
?我以前使用过DirectX 11,并编程了一个粒子系统,该系统也使用了计算着色器。但是现在我想切换到OpenGL。这是我上周刚开始的第一个API项目。因此,我还需要学习很多东西。:)因为没有真正有用的文档或有用的教程来涵盖有关计算着色器的每个细节,所以我使用了这个示例,并使用了glVertexPointer。哦,亲爱的!我想我应该多休息一下!谢谢,现在一切都很好。很抱歉用这种陈词滥调来打扰你。