OpenGL 中的无限循环绘图和断线问题

发布于 2025-01-01 07:48:46 字数 2866 浏览 3 评论 0原文

无限循环问题

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

在此处输入图像描述

我通过包含无限循环来生成此效果在 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<1000) 。这将在屏幕上绘制 1000 条线。当我以 1280x960 窗口大小运行此更改时,窗口被绘制了 2 次。第一次绘制的线条显示为断线,如上图所示。当绘制 1000 条线时,窗口会再次被清除并再次绘制,但这次线按应有的方式显示。为什么会发生这种情况。

Infinite Loop Question

I want to achieve the effect as shown the picture:

enter image description here

I am generating this by including an infinite loop inside the glutDisplayFunct callback function, and which is not good as i cannot then process any input from the keyboard. The other method of which i can think is to probably use the glut's explicit window refresh functions.

I want to know how can i insert an infinite loop and also check for keyboard input. Here is the sample code i have made. It simply implements the DDA algorithm and attempts to draw infinite lines by generating random coordinates and colours.

#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;
}

Broken lines when first drawn

Also i have an additional question, which is like this:

When i uncomment the infinite loop (the while (i)) inside the test_dda function and run the executable with 1280x960 screen size every line drawn shows as broken lines, they seems look something like dashed lines. But, if i do not infinitely loop in this function and draw the lines with some other way, like forcing OpenGL to redraw, the lines shows as they should be displayed. I have noticed that when drawing the first time, the lines show broken. The broke lines of which i am talking is shown below:

enter image description here

To understand what i am saying do the following to get the effect. Change the while (i) to while (i<1000) . This will draw 1000 lines on the screen. When i run with this change with 1280x960 window size, the window is drawn 2 times. The first time the lines are drawn shows as broken as the above image. The moment 1000 lines are drawn, the window is cleared again the it is drawn again, but this time the lines shows as they should be. Why this is happening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

合久必婚 2025-01-08 07:48:46

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

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

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

You don't have to. The infinite loop already happens inside glutMainLoop(). It will call your display function over and over again till the program is closed. To keep the output of previous frames (i.e. drawing over them), don't clear the color buffer with glClear().

As for the broken lines: Don't draw lines pixel by pixel. While I didn't have a closer look, you most likely have some discrepancy caused by your view/projection matrix (i.e. you're drawing the dots with too much spacing). Instead, use OpenGL calls to draw lines.

What you're trying to do here is essentially trying to do software rendering on top of hardware accelerated rendering, which is just weird and not really recommended.

始终不够爱げ你 2025-01-08 07:48:46

每次需要重新绘制窗口时都会调用“display”函数(在您的情况下是test_dda)。如果您处于显示函数内的无限循环中,则 GLUT 中的事件处理代码不会发生任何运行变化。

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

The "display" function (test_dda in your case) is called every time the window needs to be redrawn. The event handling code in GLUT get no change of running if you are in an infinite loop inside the display function.

Instead use a timer, and draw one line in the timer function and then call a function to force GLUT to redraw the window, where you "flush" the GL pipe.

百思不得你姐 2025-01-08 07:48:46

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

不要误会我的意思 :)

如果重点是一遍又一遍地不断绘制线条,一种可能的解决方案是以这种方式分段该过程:

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

,依此类推......

I think that the starting solution you are adopting is conceptually wrong.

Don't take me bad :)

If the point is to draw constantly lines over and over, one possible solution would be to segment the process in this way:

  • FRAME 1 STEP1: You draw the lines on a framebuffer mapped to a texture over a quad containing the working texture
  • FRAME 1 STEP2: You draw a quad with the working texture
  • GLUT INPUT CALLBACK
  • FRAME 2 STEP1: You draw the lines on a framebuffer mapped to a texture over a quad containing the working texture
  • FRAME 1 STEP2: You draw a quad with the output working texture
  • GLUT INPUT CALLBACK

And so on.....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文