You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL Boids群集模拟:大数量个体时画面闪烁问题求助

OpenGL Boids群集模拟渲染闪烁问题

我正在用OpenGL实现Boids群集模拟项目,用来测试自己的OpenGL知识,目标是在保持30FPS以上的前提下,尽可能提升屏幕上渲染的Boids数量。但遇到了瓶颈:

  • 当Boids数量达到2^16及以上时(每个Boid由3个三维float顶点组成,z值固定为0),画面开始出现闪烁,Boids会随机消失和重现
  • 这种情况仅在程序运行初期出现,当Boids形成集群、视觉上聚集后,闪烁现象就停止了
  • 我怀疑这个2^16的数值和GLshort的16位比特数有关,可能存在数值溢出问题

关键代码片段

std::vector<float> vertices(flock.boids.size()*9, 0.f);

unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0])*static_cast<uint>(vertices.size()), vertices.data(), GL_DYNAMIC_DRAW);

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

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);

float FPS_sum = 0;
size_t frames = 0;
float CPS_sum = 0;
std::chrono::high_resolution_clock::time_point start;
// render loop
while(!glfwWindowShouldClose(window))
{
    processInput(window);

    //Begin CPS timer
    start = std::chrono::high_resolution_clock::now();
    //Computation Step
    std::vector<point_bucket<Boid>> tree;
    point_bucket<Boid> base(0, 0, 2, 2, flock.boids);
    base_split(base, 16, tree, 20);
    for(auto& elm: tree)
    {
        flock.Update(elm.bucket);
    }
    flock.Mirror();
    CPS_sum+=1000.f/std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start).count();

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

    glUseProgram(shaderProgram);

    //Begin FPS timer
    start = std::chrono::high_resolution_clock::now();

    glBindVertexArray(VAO);
    updateVertices(flock.boids, window, vertices);
    updateBuffer(VBO, 0, vertices.data(), sizeof(vertices[0])*static_cast<uint>(vertices.size()), GL_ARRAY_BUFFER);
    size_t draw_running_total = vertices.size()/3;
    GLint draw_offset = 0;
    while(draw_running_total > 0)
    {
        glDrawArrays(GL_TRIANGLES, draw_offset, draw_running_total > draw_size? draw_size: draw_running_total);
        draw_running_total -= draw_size;
        draw_offset += draw_size;
    }

    // check and call events and swap the buffers
    glfwSwapBuffers(window);
    glfwPollEvents();

    // PULL FPS FOR DRAW
    FPS_sum+=1000.f/std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start).count();
    
    frames++;
    if(frames==100)
    {
        std::cout << "Average across 100 frames... 
" << FPS_sum/frames << " FPS
"
        << CPS_sum/frames << " CPS
";
        FPS_sum = 0;
        CPS_sum = 0;
        frames = 0;
    }

    //END PULL FOR FPS

}

void updateBuffer(uint &id, uint offset, void *data, uint size, GLenum shaderType) 
{
    glBindBuffer(shaderType, id);
    glBufferSubData(shaderType, offset, size, data);
}

已排查情况

  • 查阅过Stack Overflow相关帖子,大多涉及多余的缓冲区交换问题,但我只在绘制循环末尾执行一次缓冲区交换,排除该原因
  • Reddit上有类似问题提到用FBO可能解决,但没找到根本原因

希望能得到帮助!

内容的提问来源于stack exchange,提问作者Emre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:12:11