【发布时间】:2016-07-03 11:32:31
【问题描述】:
我正在使用 OpenGL 开发一个小型粒子系统。
问题是在计算着色器中更新位置似乎不起作用。
代码如下:
-
缓冲区
struct ParticleInfo { Vec4f position; // w: s coordinate Vec4f normal; // w: t coordinate float materialIndex; Vec3f oldPosition; }; -
初始化缓冲区
glGenVertexArrays(1, &mParticleVAO); glBindVertexArray(mParticleVAO); glGenBuffers(1, &mParticleVBO); glBindBuffer(GL_ARRAY_BUFFER, mParticleVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(ParticleInfo) * mNumParticles, particleData.data(), GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleInfo), (void*)NULL); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleInfo), (void*)(NULL + sizeof(Vec4f))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleInfo), (void*)(NULL + 2*sizeof(Vec4f))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); -
使用计算着色器更新缓冲区
gl->setUniform(mParticleMoveProgram->getUniformLoc("numParticles"), mNumParticles); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mParticleVBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mAttractorSSBO); int localSizeX = 64*8; int groupSizeX = (mNumParticles + localSizeX - 1) / localSizeX; glDispatchCompute(groupSizeX, 1, 1); glMemoryBarrier(GL_ALL_BARRIER_BITS); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); -
着色器代码
#version 450 layout(local_size_x = 64) in; struct ParticleInfo { vec4 position; // modify only the position; vec4 normal; float materialIndex; vec3 oldPosition; }; struct Attractor { vec3 position; float mass; }; layout(binding = 0, std430) buffer ParticleArray { ParticleInfo particles[]; }; layout(binding = 1, std430) buffer AttractorArray { Attractor attractors[]; }; uniform int numParticles; vec3 verlet(in vec3 a, in vec3 x, in vec3 xOld, in float dt) { return 2.0 * x - xOld + a * dt*dt; } void main() { const int PARTICLES_PER_THREAD = 8; int index = int(gl_LocalInvocationIndex)*PARTICLES_PER_THREAD; if (index >= numParticles) return; Attractor attr = attractors[0]; const float G = 9.8; for (int i = 0; i < PARTICLES_PER_THREAD; ++i) { particles[i+index].position = vec4(0.0); particles[i+index].normal = vec4(0.0); particles[i+index].oldPosition = vec3(0.0); } }
【问题讨论】:
-
不工作:我的意思是粒子保持在相同的初始位置,我想将它们全部设置为位置 0。
-
你怎么知道他们在同一个位置?你是在渲染它却没有看到它们移动吗?
-
粒子类似于特定的形状。它们都是从某个网格中的三角形中采样的。
-
你的cpu端
ParticleInfo结构与std430的对齐规则不匹配,所以shader中的ParticleInfo和Attractor会看到不同的数据,尤其是你使用数组的时候这些结构。如果您将标量float与vec3一起打包到vec4中,您可以让您(和您的 GPU)的生活更轻松。 -
作为derhass声明的补充,请看this question/answer
标签: opengl glsl particle-system particles compute-shader