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
相关产品推荐
相关产品推荐

