具有 freeglut 连续重新计算图形闪烁的 C++ OpenGL

标签 c++ opengl animation graph freeglut

我写了这段代码来制作洛伦兹吸引子的动画:

#include <iostream>
#include <GL/freeglut.h>
double x = 1, y = 1, z = 1, a = 10, b = 28, c = 8/3, precision = 0.000001, lastx = x, lasty = y, lastz = z;
int counter = 0;
void draw() {
    glBegin(GL_LINES);
        glVertex2d(lastx, lasty);
        glVertex2d(x, y);
    glEnd();
    lastx = x;
    lasty = y;
    double dxdt = a*(y-x);
    double dydt = x*(b-z)-y;
    double dzdt = x*y-c*z;
    x += precision*dxdt;
    y += precision*dydt;
    z += precision*dzdt;
    counter++;
    if (counter == 40000)
    {
        glutSwapBuffers();
        counter = 0;
    }
    glutPostRedisplay();
}
void mykey(unsigned char mychar, int x, int y) {
    if (mychar == 27) {
        exit(0);
    }
}
int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(1000, 1000);
    glutCreateWindow("Lorenz Attractor");
    glutDisplayFunc(draw);
    glutKeyboardFunc(mykey);
    glClearColor(0, 0, 0, 1);
    glColor4d(0, 0, 1, 1);
    glViewport(0, 0, 1000, 1000);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-30, 30, -30, 30);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_POINT_SMOOTH);
    glPointSize(1);
    glutFullScreen();
    glutMainLoop();
}

问题是,除了用2个点拼接数千条线外,我不知道如何绘制连续图形。过了一会儿它开始闪烁,我想这就是原因。关于如何修复的任何想法?谢谢!

附言此外,如果您觉得特别慷慨,请给我一些关于如何实现缩放和在图表移动端的白点的提示。如果您看到任何可以改进的地方,请告诉我。再次感谢!

编辑:

使用带有 glFlush() 的单个缓冲区解决了这个问题,双缓冲区只有在有一种方法可以在交换之前将前缓冲区复制到后缓冲区的情况下才能工作。如果有这样的方法,请告诉我。

最佳答案

您正在使用双缓冲 opengl 窗口。当你想在这种情况下做动画时,你必须

  • 绘制要显示到后台缓冲区的完整帧
  • 交换缓冲区以显示帧
  • 从头开始绘制下一帧

这里的关键点是,在 SwapBuffers 调用之后,后台缓冲区的内容变为未定义。您的实现恰好在一些以前的帧缓冲区之间切换。这意味着您绘制 40000 行,交换缓冲区以便显示它们,将接下来的 40000 行绘制到另一个不包含前 40000 行的缓冲区,依此类推,所以会出现闪烁。

如果您希望您的绘图“扩展”每一帧,您有多种选择:

  1. 实际上将您的线条存储在某种数据结构中并在每一帧重绘整个图像
  2. 交换后将最后一帧的结果复制到新的后台缓冲区。 (更有效的方法是渲染到纹理)。
  3. 使用单缓冲(将 GLUT_DOUBLE 标志替换为 GLUT_SINGLE 并使用 glFlush 而不是 glutSwapBuffers)<

第三个选项对您来说可能是最好(也是最简单)的解决方案,但从概念上讲,它是最差的。您应该重新考虑在 OpenGL 中实现动画的方式。

关于具有 freeglut 连续重新计算图形闪烁的 C++ OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34485979/

相关文章:

c# - WPF 中的 OpenGL 控件 - 如何?

c++ - 我正在用 OpenGL 编写一个程序来创建一个摆动的摆锤

jquery - 使用 ':active' 选择器后如何防止调用我的 css 动画?

c++ - 重载 << 并定义流操纵器 C++

c++ - SystemC:单个 cpp 文件中的多个模块实现

c++ - 当前渲染视频卡

OpenGL 最大 FBO 和 PBO

python - 保存 matplotlib.animation 输出 0 秒视频

c++ - 我可以从最终产品中删除 Boost.log V2 的所有效果吗?

c++ - while 循环不考虑这两个条件