【问题标题】:Infinite Loop Drawing in OpenGL and Broken Lines issueOpenGL 中的无限循环绘图和断线问题
【发布时间】:2012-01-31 18:23:44
【问题描述】:

无限循环题

我要达到如图所示的效果:

我通过在glutDisplayFunct 回调函数中包含一个无限循环来生成它,这不好,因为我无法处理来自键盘的任何输入。我能想到的另一种方法可能是使用 glut 的显式窗口刷新功能。

我想知道如何插入无限循环并检查键盘输入。这是我制作的示例代码。它只是简单地实现了 DDA 算法,并尝试通过生成随机坐标和颜色来绘制无限的线条。

#include <stdio.h>
#include <GL/glut.h>

int width;
int height;

void dda (int x1, int y1, int x2, int y2)
{
  int del_x, del_y, sample_steps, i = 1;
  double x_incr, y_incr, x, y;

  del_x = x2 - x1;
  del_y = y2 - y1;
  sample_steps = (abs (del_x) > abs (del_y)) ? abs (del_x) : abs (del_y);

  x_incr = del_x / (double) sample_steps;
  y_incr = del_y / (double) sample_steps;

  x = x1;
  y = y1;


  glBegin (GL_POINTS);
  while (i<=sample_steps)
  {
    glVertex2f ((2.0 * x)/width, (2.0 * y)/height);
    x += x_incr;
    y += y_incr;
    i++;
  }
  glEnd ();

  glFlush ();
}

void keypress_handler (unsigned char key, int x, int y)
{
  if (key == 'q' || key == 'Q')
  {
    glutLeaveMainLoop ();
  }
}

void init_screen (void)
{
  glMatrixMode (GL_PROJECTION);
  glClearColor (0, 0, 0, 1);
  glClear (GL_COLOR_BUFFER_BIT);
  glLoadIdentity ();
  glMatrixMode (GL_MODELVIEW);
}

void test_dda (void)
{
  int x1, y1, x2, y2;
  float r, g, b;

  int i=1;

  glClear (GL_COLOR_BUFFER_BIT);
  srand (time(NULL));
  width = glutGet (GLUT_WINDOW_WIDTH);
  height = glutGet (GLUT_WINDOW_HEIGHT);

  while (i)
  {
    x1 = rand () % width  - (width  /2);  /* Global */
    y1 = rand () % height - (height /2); /* Global */
    x2 = rand () % width  - (width  /2);  /* Global */
    y2 = rand () % height - (height /2); /* Global */

    r = rand () / (float) RAND_MAX;
    g = rand () / (float) RAND_MAX;
    b = rand () / (float) RAND_MAX;

    glColor3f (r, g, b);
    dda (x1, y1, x2, y2);
    printf ("\r%d", i);
    i++;
  }

}

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D (-1, 1, -1, 1);
  glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char *argv[])
{
  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
  init_screen ();
  glutCreateWindow ("DDA");
  glutDisplayFunc (test_dda);
  glutReshapeFunc (reshape);
  glutKeyboardFunc (keypress_handler);

  glutMainLoop ();

  printf ("\n");
  return 0;
}

首次绘制时的断线

另外我还有一个问题,是这样的:

当我取消注释test_dda 函数内的无限循环(while (i))并以 1280x960 屏幕大小运行可执行文件时,每条绘制的线都显示为虚线,它们看起来像虚线。但是,如果我没有在这个函数中无限循环并用其他方式绘制线条,比如强制 OpenGL 重绘,线条就会显示为它们应该显示的样子。我注意到第一次绘制时,线条显示为断线。我所说的断线如下所示:

要理解我在说什么,请执行以下操作以获得效果。将 while (i) 更改为 while (i&lt;1000) 。这将在屏幕上绘制 1000 条线。当我以 1280x960 的窗口大小运行此更改时,窗口被绘制了 2 次。第一次绘制的线条显示为如上图所示的断线。绘制 1000 条线的那一刻,窗口再次被清除并再次绘制,但这一次线条显示为应有的样子。为什么会这样。

【问题讨论】:

    标签: c opengl graphics glut infinite-loop


    【解决方案1】:

    您不必这样做。无限循环已经发生在glutMainLoop() 内部。它会一遍又一遍地调用你的显示函数,直到程序关闭。要保留前一帧的输出(即在它们之上绘制),请不要使用 glClear() 清除颜色缓冲区。

    至于虚线:不要逐像素画线。虽然我没有仔细观察,但您的视图/投影矩阵很可能存在一些差异(即您绘制的点间距太大)。而是使用 OpenGL 调用来绘制线条。

    您在这里尝试做的实际上是尝试在硬件加速渲染之上进行软件渲染,这很奇怪,并不推荐。

    【讨论】:

    • 代码的主要目标是手动实现画线算法,而不是使用内部例程。我使用的算法是非常基本的算法(DDA),并且运行良好。像素没有以太大的间距绘制,对于 dely/delx 1 则反之亦然。所以绘制的线条是连续的,不会有任何间隙。
    • 另一方面,显示功能不会被一遍又一遍地绘制,例如,当我最小化正在重绘的窗口时,或者当我调整正在重绘的窗口大小时,绘制速度非常慢(不像while (1) 循环中的那样。
    • 你必须强制重绘,例如完成渲染后,只需调用glutPostRedisplay() 即可重绘下一个迭代/帧。另外,我知道您使用的算法,但我猜这些差距仍然是由于这里不打算使用这种方法造成的(例如,它更适合直接像素操作)。差距可能是由于四舍五入造成的(你试过glSmooth()吗?)。
    • 但问题是,当我打印像素值(数量)时,它们显示为相邻的图。同样只有第一次绘制显示虚线,随后的重绘正确显示了线。这是我要问的主要问题。
    • 不确定,但我猜有些状态/矩阵已关闭。例如。在绘制之前不要调用 reshape 来以相同的方式设置投影矩阵(除非在第一次打开窗口时由 GLUT 完成;这里没有经验)。
    【解决方案2】:

    每次需要重绘窗口时都会调用“显示”函数(在您的情况下为test_dda)。如果您在显示函数内处于无限循环中,则 GLUT 中的事件处理代码不会更改运行。

    改为使用计时器,并在计时器函数中绘制一条线,然后调用一个函数来强制 GLUT 重绘窗口,在该窗口中“刷新”GL 管道。

    【讨论】:

      【解决方案3】:

      我认为您采用的初始解决方案在概念上是错误的。

      别欺负我:)

      如果重点是一遍又一遍地画线,一种可能的解决方案是以这种方式分割流程:

      • 帧 1 第 1 步:在帧缓冲区上绘制线条,该帧映射到包含工作纹理的四边形上的纹理
      • FRAME 1 STEP2:使用工作纹理绘制一个四边形
      • GLUT 输入回调
      • 帧 2 第 1 步:在帧缓冲区上绘制线条,该帧映射到包含工作纹理的四边形上的纹理
      • FRAME 1 STEP2:使用输出工作纹理绘制一个四边形
      • GLUT 输入回调

      等等.....

      【讨论】:

      • 绝对不是这样,我是 glut 和 opengl 的新手,因此需要深入研究。目前理解您建议的方式有点复杂,但我会阅读这些并尝试一下。
      猜你喜欢
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-29
      • 1970-01-01
      相关资源
      最近更新 更多