【问题标题】:SSBO writes are not visibleSSBO 写入不可见
【发布时间】:2016-07-03 11:32:31
【问题描述】:

我正在使用 OpenGL 开发一个小型粒子系统。
问题是在计算着色器中更新位置似乎不起作用。

代码如下:

  1. 缓冲区

    struct ParticleInfo {
    
        Vec4f position; // w: s coordinate
        Vec4f normal; // w: t coordinate
        float materialIndex;
        Vec3f oldPosition;
    
    };
    
  2. 初始化缓冲区

    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);
    
  3. 使用计算着色器更新缓冲区

         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);
    
  4. 着色器代码

    #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


【解决方案1】:

正如@derhass 评论的那样。内存结构不匹配。每个线程的正确索引似乎也存在问题。我通过将每个线程的索引设置为:

index = PARTICLES_PER_THREAD * int(gl_WorkGroupSize.x * gl_WorkGroupID.x + gl_LocalInvocationID.x);

感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多