OpenGL 中的无限循环绘图和断线问题
无限循环问题
我想达到如图所示的效果:
我通过包含无限循环来生成此效果在 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:
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:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你不必这样做。无限循环已经发生在 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 withglClear()
.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.
每次需要重新绘制窗口时都会调用“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.
我认为您采用的起始解决方案在概念上是错误的。
不要误会我的意思 :)
如果重点是一遍又一遍地不断绘制线条,一种可能的解决方案是以这种方式分段该过程:
,依此类推......
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:
And so on.....