在 OpenGL 中调整大小 window:垃圾输出
Resizing window in OpenGL: Garbage Output
我在 Mac OS X 上使用带有 OpenGL 的 GLUT。当我通过拖动 window 边缘调整 window 大小时,window充满了垃圾值。代码附在下面。我发现清除垃圾的唯一方法是调用 glClear(),当然,我不想这样做。
问题是我不想要垃圾值。我不明白为什么我也会得到这样的值。
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else
#include <GL/glut.h>
#endif
void myInit();
void display();
void reshape(int x, int y);
void keyboard(unsigned char c, int x, int y);
void mouse(int b, int s, int x, int y);
int width;
int height;
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
myInit();
glutMainLoop();
return 0;
}
void myInit(){
glutInitDisplayMode(GLUT_MULTISAMPLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
glutCreateWindow("Hello World!");
glClearColor(0.2,0.2,0.2,1);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutReshapeFunc(reshape);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 0.5,\
0.0,0.0,0.0,\
0.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
void display(){
printf ("))display\n");
glFlush();
}
void keyboard(unsigned char c, int x, int y){
if (c == 27 || c == 81 || c == 113) exit(0);
else if (c == 67 || c == 99){
printf("CLEAR!\n");
glClear(GL_COLOR_BUFFER_BIT);
glutPostRedisplay();
}
}
void putDot(int x, int y){
glBegin(GL_POINTS);
glVertex3f(x,height-y,0);
glEnd();
glutPostRedisplay();
}
void mouse(int b, int s, int x, int y){
if (b == GLUT_LEFT_BUTTON && s == GLUT_DOWN){
printf("MouseD\n");
putDot(x,y);
}
}
void reshape(int x, int y){
printf ("))reshape\n");
width = x;
height = y;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,width, 0,height, -10,10);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
编辑:我在 Ubuntu 14.04 上遇到了类似的问题。所以麻烦一定是我的编码(当然!)。
OpenGL 不是场景图(我不再计算我已经在 SO 上写了多少次)。它只是一次绘制一个点、线和三角形到像素帧缓冲区。一旦画好了就可以了。
当您调整 window 的大小时,其帧缓冲区布局会发生变化。如果添加像素,它们的初始值为 undefined。由您来为这些像素填充值。通常在调整 window 大小时,操作系统会向您的程序发送消息,它需要重新绘制其 window 内容。 GLUT 为此使用 display 回调。您的程序的显示回调不执行任何操作(除了调用 glFlush
,如果前面没有绘图调用,则调用 no-op)。
您唯一的绘图调用发生在输入事件处理程序中。这绝对是 错误的 绘图调用的地方,至少不是主要的 window 帧缓冲区。对于它的价值,事件处理程序中甚至可能没有 OpenGL 上下文(在 GLUT 中有,但恕我直言,这是一种疏忽)。在事件处理程序中,您应该只处理事件并设置稍后控制绘图的变量。
所有绘图(这意味着调用 glVertex
或 glDraw…
)应该只( 并且只 )在 GLUT 显示回调中(或转到a off-screen renderbuffer/texture 通过帧缓冲区对象)。
如果您是新手并且正在使用 GLUT,则有一个简单的规则可以防止您陷入大多数陷阱:不得调用以 gl…
开头的函数(这不会在显示回调函数以外的任何函数中表示 glut…
或 glew…
,只是 gl
然后大写(我知道大多数,如果不是所有教程都违反此规则;不要不要让他们愚弄你)。如果您遵循该规则,您会发现很大一部分 OpenGL 新手问题都会消失。
我在 Mac OS X 上使用带有 OpenGL 的 GLUT。当我通过拖动 window 边缘调整 window 大小时,window充满了垃圾值。代码附在下面。我发现清除垃圾的唯一方法是调用 glClear(),当然,我不想这样做。
问题是我不想要垃圾值。我不明白为什么我也会得到这样的值。
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else
#include <GL/glut.h>
#endif
void myInit();
void display();
void reshape(int x, int y);
void keyboard(unsigned char c, int x, int y);
void mouse(int b, int s, int x, int y);
int width;
int height;
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
myInit();
glutMainLoop();
return 0;
}
void myInit(){
glutInitDisplayMode(GLUT_MULTISAMPLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
glutCreateWindow("Hello World!");
glClearColor(0.2,0.2,0.2,1);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutReshapeFunc(reshape);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 0.5,\
0.0,0.0,0.0,\
0.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
void display(){
printf ("))display\n");
glFlush();
}
void keyboard(unsigned char c, int x, int y){
if (c == 27 || c == 81 || c == 113) exit(0);
else if (c == 67 || c == 99){
printf("CLEAR!\n");
glClear(GL_COLOR_BUFFER_BIT);
glutPostRedisplay();
}
}
void putDot(int x, int y){
glBegin(GL_POINTS);
glVertex3f(x,height-y,0);
glEnd();
glutPostRedisplay();
}
void mouse(int b, int s, int x, int y){
if (b == GLUT_LEFT_BUTTON && s == GLUT_DOWN){
printf("MouseD\n");
putDot(x,y);
}
}
void reshape(int x, int y){
printf ("))reshape\n");
width = x;
height = y;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,width, 0,height, -10,10);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
编辑:我在 Ubuntu 14.04 上遇到了类似的问题。所以麻烦一定是我的编码(当然!)。
OpenGL 不是场景图(我不再计算我已经在 SO 上写了多少次)。它只是一次绘制一个点、线和三角形到像素帧缓冲区。一旦画好了就可以了。
当您调整 window 的大小时,其帧缓冲区布局会发生变化。如果添加像素,它们的初始值为 undefined。由您来为这些像素填充值。通常在调整 window 大小时,操作系统会向您的程序发送消息,它需要重新绘制其 window 内容。 GLUT 为此使用 display 回调。您的程序的显示回调不执行任何操作(除了调用 glFlush
,如果前面没有绘图调用,则调用 no-op)。
您唯一的绘图调用发生在输入事件处理程序中。这绝对是 错误的 绘图调用的地方,至少不是主要的 window 帧缓冲区。对于它的价值,事件处理程序中甚至可能没有 OpenGL 上下文(在 GLUT 中有,但恕我直言,这是一种疏忽)。在事件处理程序中,您应该只处理事件并设置稍后控制绘图的变量。
所有绘图(这意味着调用 glVertex
或 glDraw…
)应该只( 并且只 )在 GLUT 显示回调中(或转到a off-screen renderbuffer/texture 通过帧缓冲区对象)。
如果您是新手并且正在使用 GLUT,则有一个简单的规则可以防止您陷入大多数陷阱:不得调用以 gl…
开头的函数(这不会在显示回调函数以外的任何函数中表示 glut…
或 glew…
,只是 gl
然后大写(我知道大多数,如果不是所有教程都违反此规则;不要不要让他们愚弄你)。如果您遵循该规则,您会发现很大一部分 OpenGL 新手问题都会消失。