我正在使用計算着色器工作在粒子系統上。我把我所有的粒子放在着色器 - 存儲緩衝區中。一個粒子包含兩個頂點,即當前位置和前一個位置。着色器存儲緩衝區中的OpenGL頂點
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);
}
您的代碼是現代OpenGL和傳統OpenGL的驚人集合。它是如何進步到足以使用計算着色器並對內存同步問題有所瞭解的(你仍然在使用錯誤的屏障,順便說一句,因爲你的代碼碰巧運行並不意味着它會保證這樣做),但你使用像'glVertexPointer'這樣的過時函數? –
我在過去使用了DirectX 11,並編寫了一個粒子系統,該系統也使用了計算着色器。但是現在我想切換到OpenGL。所以這是我上個星期剛開始使用這個API的第一個項目。所以我仍然需要學習很多東西。 :) 由於沒有真正有用的文檔或有用的教程,其中涵蓋了有關計算着色器的每個細節,所以我使用了這個例子,並且使用了glVertexPointer。 http://education.siggraph.org/media/conference/S2012_Materials/ComputeShader_6pp.pdf – Stan