PDA

View Full Version : Particles move toward a weird direction



A_Shuang
04-08-2015, 10:08 AM
I want to implement a particle system simulating the raining effects with a compute shader. In the fragment shader, I simply discard the pixel when the lifespan is 0 (not sure if it's a good way). The living particles are expected to move along -y direction, and those dead should not be displayed. But the result comes out to be that all particles are displayed, and those alive behave correctly, and others which is dead turn out to move in a wrong direction -x. Here is the compute shader code:


"#version 430 \n" +
"layout (local_size_x = 1000) in; \n" +
" \n" +
"struct Particle \n" +
"{ \n" +
" vec4 pAnds; \n" + //position and size
" vec3 velocity; \n" +
" float lifespan; \n" +
" float age; \n" +
"}; \n" +
" \n" +
"layout (std430, binding = 0) buffer members_in \n" +
"{ \n" +
" Particle particle[]; \n" +
"} input_data; \n" +
" \n" +
"shared int shared_newParticles = 480 / 60; \n" +
" \n" +
"void main() \n" +
"{ \n" +
" int id = int(gl_GlobalInvocationID.x); \n" +
" \n" +
" float timestep = 1.0 / 60.0; \n" +
" \n" +
" if (input_data.particle[id].lifespan > 0) \n" +
" { \n" +
" input_data.particle[id].age += timestep; \n" +
" \n" +
" if (input_data.particle[id].age > input_data.particle[id].lifespan) \n" +
" { \n" +
" input_data.particle[id].lifespan = 0; \n" +
" } \n" +
" else \n" +
" { \n" +
" input_data.particle[id].pAnds.y += -0.1; \n" +
" } \n" +
" } \n" +
" else if (input_data.particle[id].lifespan == 0) \n" +
" { \n" +
" if (shared_newParticles > 0) \n" +
" { \n" +
" input_data.particle[id].pAnds = vec4(input_data.particle[id].pAnds.x, 20, input_data.particle[id].pAnds.z, input_data.particle[id].pAnds.w); \n" +
" input_data.particle[id].lifespan = 1.0; \n" +
" input_data.particle[id].age = 0.0; \n" +
" \n" +
" shared_newParticles--; \n" +
" } \n" +
" } \n" +
"}"


Setting up buffers:

int dataSize = (4 + 3 + 1 + 1) * Float.SIZE / 8;//
int buffSize = particleCount * dataSize;

gl.glGenBuffers(vboCount, vboBuff);

gl.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, vboBuff.get(0));
gl.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, buffSize, null, GL4.GL_DYNAMIC_COPY);

//generate vao
gl.glGenVertexArrays(vaoCount, vaoBuff);
gl.glBindVertexArray(vaoBuff.get(0));

gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboBuff.get(0));
gl.glVertexAttribPointer(verPosLoc, 4, GL4.GL_FLOAT, false, dataSize, 0);
gl.glVertexAttribPointer(lsLoc, 1, GL4.GL_FLOAT, false, dataSize, (4 + 3) * Float.SIZE / 8);

gl.glVertexAttribDivisor(verPosLoc, 1);
gl.glVertexAttribDivisor(lsLoc, 1);

gl.glEnableVertexAttribArray(verPosLoc);
gl.glEnableVertexAttribArray(lsLoc);

gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboBuff.get(0));

ByteBuffer byteBuff = gl.glMapBufferRange(GL4.GL_ARRAY_BUFFER, 0, buffSize, GL4.GL_MAP_WRITE_BIT | GL4.GL_MAP_INVALIDATE_BUFFER_BIT);

for (int i = 0; i < particleCount; i++)
{
byteBuff.putFloat(((float) Math.random() - 0.5f) * 20f);
byteBuff.putFloat(((float) Math.random() * 25));// + 25f
byteBuff.putFloat(((float) Math.random() - 0.5f) * 20f);
byteBuff.putFloat(0.02f);

byteBuff.putFloat(0);
byteBuff.putFloat(-16f);
byteBuff.putFloat(0);

byteBuff.putFloat(0);

byteBuff.putFloat(0);
}

gl.glUnmapBuffer(GL4.GL_ARRAY_BUFFER);


I have narrowed down the error, it should be the std430 qualifier that caused the problem. But why?

Firadeoclus
04-09-2015, 03:29 AM
I have narrowed down the error, it should be the std430 qualifier that caused the problem. But why?
Because of alignment rules. With std430 layout a vec4 is 16-byte aligned, so your struct Particle is also 16-byte aligned. The size of the struct is rounded up to a multiple of the alignment, so the struct actually takes 48 bytes, not 9 * 4 = 36 bytes as your Java code expects.