以下代码完美无缺,没有致命错误但是,当我使用参数" w"," h" in" gluortho2d"作为重塑函数中的gluortho2d(0,w,h,0),我在屏幕上得到文本,而如果我把这些参数放在" 0,0"作为gluortho2d(0,0,0,0)我得到了盒子的形状。 如何在屏幕上同时获取它们(框和文本)?
#include"glut.h"
void drawBitmapText(char *string, float x, float y, float z);
void reshape(int w, int h);
void display(void);
void drawBitmapText(char *string, float x, float y, float z)
{
char *c;
glRasterPos3f(x, y, z);//define position on the screen where to draw text.
for (c = string; *c != '\0'; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void)
{
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Usama OGL Window");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
答案 0 :(得分:1)
不遵循错误的教程并将调用放在glViewport
和投影矩阵设置的唯一有效位置:显示功能。在重塑处理程序中设置视口和投影矩阵是一个反模式。不要这样做。
这样做
void display(void)
{
int const w = glutGet(GLUT_WINDOW_WIDTH);
int const h = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(-1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
/* viewport doesn't change in this
* application, but it's perfectly
* valid to set a different
* glViewport(...) here */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
为什么在重塑处理程序中设置视口和投影参数是错误的?嗯,你刚才经历过这样的理由:他们不是"一个尺寸适合所有"状态和整个渲染稍微复杂的帧,不仅仅是绘制的网格,你想要在整个渲染过程中混合和匹配不同的视口和投影。这是一个(不完整的)列表,在渲染单个帧时需要具有不同的视口和投影:
由于仅在稍微复杂的OpenGL绘图中多次更改视口和投影状态,因此
a)在重塑处理程序中设置它的意义为零:无论处理程序集将仅在第一帧的绘制开始时设置,此后框架绘图代码本身必须重置为重塑处理程序设置的内容。那么为什么还要在重塑处理程序中麻烦呢?
b)在重塑处理程序中放置视口和投影设置代码从长远来看是一种负担,因为它可能会导致程序的其他部分依赖于此。如果发生这种情况,一旦你意识到你的错误,并尝试将视口和投影设置代码移动到它所属的位置,依赖于它的程序的其他部分从重塑处理程序中断调用,你也必须修复它们。 / p>总而言之,没有理由在重塑处理程序中放置任何与绘图相关的调用(并且glViewport和投影设置肯定与绘图相关)。当然"一次"那里的初始化非常精细,即如果你想调整FBO渲染目标的大小以匹配窗口,或者你想要准备一个稍后重复应用的叠加图像。
答案 1 :(得分:0)
你可以让这更简单。对于您正在做的事情,根本不需要为设置转换而烦恼。
看起来,对于这个框,你试图在两个坐标方向上使用[-1.0,1.0]范围内的坐标。这对应于OpenGL NDC(标准化设备坐标)坐标系,它是应用模型视图和投影变换后顶点的坐标空间。如果将它们保留在默认单位矩阵中,则可以直接在NDC空间中指定坐标。换句话说,要使用范围[-1.0,1.0]中的坐标,请执行......什么都不做,只需将所有内容保持为默认值。
调用时框渲染适用于您的原因:
setIntent(null);
是这次调用会导致错误,如man page:
所述如果left = right,bottom = top或near = far,则会生成GL_INVALID_VALUE。
因此会保持默认值不变,这正是您所需要的。
现在,对于文本,您似乎想要以像素为单位指定位置。您遇到的问题是gluOrtho2D(0.0, 0.0, 0.0, 0.0);
通过转换管道运行指定的坐标,这意味着,使用默认的标识模型视图和投影转换,它期望输入坐标在范围[-1.0, 1.0]就像你传递给glRasterPos*()
的坐标一样。
幸运的是,有一种非常简单的方法可以避免这种情况。这是一个非常相似的glVertex2f()
调用,唯一的区别是传递给它的坐标是在窗口坐标中,以像素为单位。
总结如下:
glWindowPos*()
来电。glMatrixMode()
来电。glLoadIdentity()
来电。在gluOrtho2D()
中,将drawBitmapText()
来电替换为:
glRasterPos3f()
唯一需要注意的是窗口坐标的原点位于 bottom 左下角。因此,如果您的文字位置是相对于左上角给出的,那么您需要以下内容:
glWindowPos2f(x, y);
要在另一个答案中解决一些误导性信息:只要您为所有渲染使用相同的视口,就可以在glWindowPos2f(x, windowHeight - y);
函数中调用glViewport()
。在更复杂的应用程序中,渲染的不同部分通常需要不同的视口(例如,当渲染到FBO或仅部分窗口时),因此您需要在适当的位置调用reshape()
渲染。但是对于一个简单的例子,你在整个窗口中进行所有渲染,在glViewport()
中调用它并没有错。