2012-10-05 143 views
4

我正在使用計算着色器工作在粒子系統上。我把我所有的粒子放在着色器 - 存儲緩衝區中。一個粒子包含兩個頂點,即當前位置和前一個位置。着色器存儲緩衝區中的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); 
} 
+0

您的代碼是現代OpenGL和傳統OpenGL的驚人集合。它是如何進步到足以使用計算着色器並對內存同步問題有所瞭解的(你仍然在使用錯誤的屏障,順便說一句,因爲你的代碼碰巧運行並不意味着它會保證這樣做),但你使用像'glVertexPointer'這樣的過時函數? –

+0

我在過去使用了DirectX 11,並編寫了一個粒子系統,該系統也使用了計算着色器。但是現在我想切換到OpenGL。所以這是我上個星期剛開始使用這個API的第一個項目。所以我仍然需要學習很多東西。 :) 由於沒有真正有用的文檔或有用的教程,其中涵蓋了有關計算着色器的每個細節,所以我使用了這個例子,並且使用了glVertexPointer。 http://education.siggraph.org/media/conference/S2012_Materials/ComputeShader_6pp.pdf – Stan

回答

6

Particle結構包含兩個vec4的。您的compute shader爲每個數組元素寫入兩個vec4

然而,這條線:

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

告訴您傳遞的vec4秒的陣列的OpenGL。你不是。您正在傳遞一個數組,其中每個元素都是兩個vec4 s。而你想跳過第二個。

所以告訴OpenGL的是,通過提供合適的步幅:

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

哦,順便說一句:你還是using the wrong barrier。僅僅因爲你的代碼碰巧起作用並不意味着它是有保證的。除非你正確地做了所有事情,否則不同步的加載/存儲操作可能會非常棘手。

+0

哦,親愛的!我想我應該休息一下了!謝謝,現在一切正常。對不起,以這樣的平庸來打擾你。 – Stan