尝试使用 OpenGL 创建粒子系统时出现分段错误

Segmentation fault error while attempting to create a particle system with OpenGL

我正在尝试创建一个简单的粒子系统,但我遇到了分段错误。我的问题似乎与我传递的顶点属性的数量有关。一个顶点有 3 个浮点数,对应于 x、y 和 z 坐标,所以如果我想创建 100 万个粒子,我将有一个包含 300 万个浮点数的数组,其中包含每个粒子的位置坐标。问题是,如果我超过一定数量的粒子,比如大约 400000,我会遇到分段错误。

部分代码如下:

#define NP  1000000

int main(void)
{
    // Init GLFW
    MyGLFW myglfw(4, 5, W, H, "Particles");
    // Create shader program
    Shader shader("shaders/shader.vs", "shaders/shader.fs");

    // Define particle's vertex attrib
    float particleData[NP * 3];
    for(uint i = 0; i < NP * 3; i++)
    {
        // Creates a new particle with random position in the given range
        Particle p(-1.0f, 1.0f);
        particleData[i++] = p.pos[0];
        particleData[i++] = p.pos[1];
        particleData[i]   = p.pos[2];
    }

    // Create Vertex Buffer Object (VBO) to store vertices into GPU memory
    uint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(particleData), particleData, GL_STATIC_DRAW);

    // Position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // Render loop
    while(!glfwWindowShouldClose(myglfw.getWindow()))
    {
        // Check input
        myglfw.processInput();

        // Rendering commands
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Activate shader
        shader.use();

        // Draw triangle through VAO
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 0, NP * 3);
        glBindVertexArray(0);

        // GLFW: swap buffers and poll IO events (e.g. keys pressed, released, mouse moved, etc.)
        glfwSwapBuffers(myglfw.getWindow());
        glfwPollEvents();
    }

    // GLFW: terminate, clearing all previously allocated GLFW resources
    myglfw.terminate();
    return 0;
}

我设法写了大约 400000-500000 个粒子,超过这个数目我遇到了分段错误。 GDB 说分割信号正好在主线的第一行,我不明白。我也试图通过直接在主函数中设置一个 long int nr = 1000000 来设置粒子数,但是我得到了同样的错误,这样 GDB 在 float particleData[nr];.[=13= 处给我一个错误]

我正在使用 VS Code 在 Linux 系统上编写和 运行 我的代码,我的 GPU 是 GTX 1070 FE。

根据评论,使用...

float particleData[NP * 3];

可能会导致堆栈溢出。您应该考虑使用 std::vector 而不是在堆栈上分配这么大的数组。以下是您的代码(希望)进行了最少的必要修改(查找 @G.M. )...

#define NP  1000000

int main(void)
{
    // Init GLFW
    MyGLFW myglfw(4, 5, W, H, "Particles");
    // Create shader program
    Shader shader("shaders/shader.vs", "shaders/shader.fs");

    // Define particle's vertex attrib
    std::vector<float> particleData(NP * 3); /* @G.M. */
    for(uint i = 0; i < NP * 3; i++)
    {
        // Creates a new particle with random position in the given range
        Particle p(-1.0f, 1.0f);
        particleData[i++] = p.pos[0];
        particleData[i++] = p.pos[1];
        particleData[i]   = p.pos[2];
    }

    // Create Vertex Buffer Object (VBO) to store vertices into GPU memory
    uint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(particleData[0]) * particleData.size(), particleData.data(), GL_STATIC_DRAW); /* @G.M. */

    // Position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // Render loop
    while(!glfwWindowShouldClose(myglfw.getWindow()))
    {
        // Check input
        myglfw.processInput();

        // Rendering commands
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Activate shader
        shader.use();

        // Draw triangle through VAO
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 0, NP * 3);
        glBindVertexArray(0);

        // GLFW: swap buffers and poll IO events (e.g. keys pressed, released, mouse moved, etc.)
        glfwSwapBuffers(myglfw.getWindow());
        glfwPollEvents();
    }

    // GLFW: terminate, clearing all previously allocated GLFW resources
    myglfw.terminate();
    return 0;