我在运行一个简单的程序时遇到了一些问题:(文本下方的代码)
我想打印一个坐标为[50,50],[-50,-50],[50,-50]和[-50,50]的正方形作为输出。
我在init()中设置了一个glOrtho矩阵,然后在我的显示函数中,我将上面坐标的正方形打印为glVertex2f(例如glVertex2f(50.0,-50.0))。这是正确的方法还是glVertex2f不将实际坐标作为值?
不管怎样,这是代码:(它编译得很好,但在图形窗口中没有显示任何内容)
#include <iostream>
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <windows.h>
#include <GL/glut.h>
#endif
#define SCR_WID 640
#define SCR_HEI 480
#include "imageloader.h"
using namespace std;
//*****************************CUSTOM FUNCS***********************************//
void init()
{
glViewport(0,0,SCR_WID,SCR_HEI);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho((double)SCR_WID,0.0,(double)SCR_HEI,0.0,-5.0,-20.0);
glMatrixMode(GL_MODELVIEW);
}
//*****************************CALLBACKS (win 1)******************************//
void resizeFunc(int w, int h)
{
glutReshapeWindow(SCR_WID,SCR_HEI);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glVertex2f(1.0,1.0);
glVertex2f(-1.0,1.0);
glVertex2f(1.0,-1.0);
glVertex2f(-1.0,-1.0);
glEnd();
glutSwapBuffers();
}
void key(unsigned char key, int x, int y)
{
if (key == 'q' || key == 27 )
exit(0);
glutPostRedisplay();
}
//**********************************main func*********************************//
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(SCR_WID,SCR_HEI);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("TestGlut");
glutReshapeFunc(resizeFunc);
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(key);
init();
glutMainLoop();
return EXIT_SUCCESS;
}
您的init函数有点奇怪
glViewport(0,0,SCR_WID,SCR_HEI);
默认视口已经是完整的窗口,因此这是多余的。
glPushMatrix();
您从未在其他地方调用glPopMatrix
或以任何其他方式操作矩阵堆栈,那么为什么要这样做呢?
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho((double)SCR_WID,0.0,(double)SCR_HEI,0.0,-5.0,-20.0);
在glOrtho
之前立即调用glLoadIdentity
是一种浪费。glOrtho
覆盖当前矩阵,所以它以前是什么并不重要。此外,glLoadIdentity
将矩阵值重置回单位矩阵的默认值,这是程序启动时的情况,因此它是双重冗余的。
此外,glOrtho参数是"左下右上近远"。通过为左侧和底部输入比右侧和顶部大的数字,可以反转X轴和Y轴。这最多会给你一个投影,将(0,0)坐标放在屏幕的右下方,这是非常不寻常的。最后,你的近平面和远平面完全位于负Z空间中。这意味着只有两个值指定的顶点(使用时为glVertex2f
)将始终被排除在外,因为它们的z坐标为隐式0。
void resizeFunc(int w, int h)
{
glutReshapeWindow(SCR_WID,SCR_HEI);
}
如果要忽略输入的宽度和高度,为什么要使用调整大小函数呢?
glBegin(GL_QUADS);
glVertex2f(1.0,1.0);
glVertex2f(-1.0,1.0);
glVertex2f(1.0,-1.0);
glVertex2f(-1.0,-1.0);
glEnd();
除了这些坐标将生成剪裁的顶点这一事实之外(因为它们的Z值隐式为0,因此在近/远剪裁区域之外),您还在规范化剪裁坐标中指定它们。如果你纠正了genpfault提到的Z形状问题(通过交换顶点3和4),那么如果你使用默认投影矩阵,这些将占据整个屏幕。通过使用屏幕像素尺寸设置正交矩阵,您已经创建了一个2像素宽、2像素高的正方形,位于屏幕的右下角。
void key(unsigned char key, int x, int y)
{
...
glutPostRedisplay();
}
为什么?如果你想让你的程序持续渲染,而不仅仅是当有人按下某个键时,那么你应该在空闲函数中使用glutPostRedisplay(),而不是在按键函数中。
int main(int argc, char *argv[])
{
...
glutIdleFunc(display);
...
}
不要将空闲功能设置为显示功能。如果你想让你的程序动画化,制作一个实际的空闲函数,调用glutPostRedisplay
。