我有一个opengl项目,我只是试图在屏幕上绘制一个红色矩形,问题是1)它很大,几乎占据整个屏幕,2)它倾斜。我是opengl的新手,所以我不了解坐标系,以及一些函数的功能,例如glOrtho()函数。
以下是代码:
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1, 0, 0); // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK
glVertex2f(-1.0f, 1.0f);
glVertex2f( 1.0f, 1.0f);
glVertex2f( 1.0f,-1.0f);
glVertex2f(-1.0f,-1.0f);
glEnd();
glFlush();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 10.0, 0, 10.0, -1.0, 1.0); //What does this do and how does it's coordinates work?
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(30.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitWindowPosition(250, 250);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
glutCreateWindow("Model View");
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
无论如何,我更愿意把它变成一种学习体验,所以请解释并链接到有用的东西!感谢。
答案 0 :(得分:5)
程序显示负责实际绘图。
void display()
{
此行清除缓冲区;缓冲区基本上是渲染图像的内存;它基本上是一个宽度和高度为600x600的矩阵。要清除意味着将矩阵的每个单元格设置为相同的值。每个单元格都是像素,并包含颜色和深度。通过这个调用,你告诉OpenGL绘制所有不透明的黑色,并将深度重置为1.为什么不透明的黑色?由于您调用 glClearColor :前三个参数是红色,绿色和蓝色组件,它们的范围在0到1之间.0,0,0表示黑色。对于您指定的最后一个组件1,表示不透明; 0将是透明的。最后一个组件称为 alpha ,并在启用 alpha blend 时使用。为什么清晰的深度是1?因为1是默认值,并且您没有调用glClearDepth来覆盖该值。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
这告诉OpenGL您想绘制四边形。
glBegin(GL_QUADS);
您希望这些四边形为红色(请记住,颜色的第一个成分是红色)。
glColor3f(1, 0, 0); // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK
现在列出四边形的顶点(它只有一个,四个顶点);所有顶点都是红色的,因为你永远不会通过调用 glColor3f 更新颜色;你可以将不同的颜色关联到每个顶点,如果选择红色(1,0,0),绿色(0,1,0),蓝色(0,0,1)和白色(1),最终结果通常非常可爱,1,1);这个四边形应该看起来像一个正方形,因为它是一个几何形状的正方形,你的窗口是一个正方形,而摄像机(用 glOrtho 定义)有一个方形的方面(调用的前四个参数)的 glOrtho 强>)。如果您没有调用 glOrtho ,您可能只会看到红色,因为默认的OpenGL坐标介于-1和1之间,因此您将覆盖整个窗口。
glVertex2f(-1.0f, 1.0f);
glVertex2f( 1.0f, 1.0f);
glVertex2f( 1.0f,-1.0f);
glVertex2f(-1.0f,-1.0f);
这意味着您完成了绘图。
glEnd();
从技术上讲,可能是OpenGL没有将您指定的任何命令发送到图形卡;为了效率原因,可以将命令排队。调用glFlush强制将命令发送到图形卡。
glFlush();
}
你编写了这个函数, init 来初始化一些OpenGL 状态,你觉得它们会在整个应用程序中保持稳定。实际上,像游戏这样的真实应用程序会显示大部分内容。例如,当玩家移动时,游戏必须不断更新相机。
void init()
{
正如我们之前所说的,您将清晰的颜色设置为不透明的黑色。
glClearColor(0.0, 0.0, 0.0, 1.0);
这里你说的是相机不是透视类型;基本上遥远的事情不会变小。它类似于人造卫星对城市的看法。特别是你正在创造一个没有居中的相机。在视野上:我建议您使用像 glOrtho(-10.0,10.0,-10.0,10.0,-1.0,1.0)这样的调用进行首次实验。对于非透视摄影机,您在此处指定的坐标将覆盖我们上面提到的约定-1到+1。尝试调整参数,使红色方块看起来很小,并居中。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 10.0, 0, 10.0, -1.0, 1.0); //What does this do and how does it's coordinates work?
在这里,您基本上将相机相对于正方形或相对于相机的正方形定位;有无限的方式来看待它。您正在定义一个几何变换,它被称为MODELVIEW的原因是它不是唯一改变模型(方形)或视图(相机)的东西)但两者都取决于你看到它的方式。但是,您的方块显示为已旋转,因为您正在调用glRotatef;将其移除,方块看起来像一个正方形。
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(30.0, 1.0, 1.0, 1.0);
深度测试是一种使用缓冲区中的深度存储来移除隐藏曲面的技术,例如3D场景中立方体的背面。你的场景是2D的,你只绘制一个四边形,所以这对你的绘图没有影响。
glEnable(GL_DEPTH_TEST);
}
在 main 中,您正在与 glut 进行交互, glut 是一个可选的子系统,它不是OpenGL的一部分,但对于执行一些只有操作的无聊且繁琐的操作很有用系统有权执行。
int main(int argc, char *argv[])
{
首先,你必须初始化过剩。
glutInit(&argc, argv);
然后定义将包含渲染图像的窗口。
glutInitWindowSize(600, 600);
glutInitWindowPosition(250, 250);
GLUT_RGB表示您的窗口仅支持红色,绿色和蓝色,并且没有alpha通道(通常情况下)。 GLUT_DEPTH意味着您的缓冲区将能够存储每个像素的深度。 GLUT_SINGLE意味着窗口是单缓冲的,即你的命令将直接在窗口上绘制;另一种选择是双缓冲,你实际上在后面缓冲区上绘制,然后你交换前面和后面的缓冲区,这样渲染的图像突然出现,而不是一个渐进的时尚。你的场景很简单,你不应该注意到GLUT_SINGLE和GLUT_DOUBLE之间的任何区别。
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
然后你实际上创建了窗口。
glutCreateWindow("Model View");
你告诉我应该调用哪个函数来渲染场景。
glutDisplayFunc(display);
您可以在此处调用 init 功能。
init();
这是一个由过剩提供的窗口循环。大多数窗口系统需要一个软件循环才能使窗口保持活动状态,并能够响应点击,拖动,调整大小和键盘敲击。
glutMainLoop();
return 0;
}
长话短说,有几个版本的OpenGL可用,它们可以使用多种语言编程,并针对多个平台。这些版本之间最重要的区别是有些使用固定功能管道(FFP),而最新版本有可编程管道。您的程序使用固定功能管道。你应该尽可能地切换到可编程管道,因为它是现代的计算机图形学方法,并且很多更灵活,即使它需要更多的编程,顾名思义。
你应该忽略我最初链接的教程,我没有立即意识到它们过时了。您应该使用the one recommended by datenwolf,或者,如果您对移动开发感兴趣,可以考虑学习OpenGL ES 2 (2很重要,因为之前的版本是固定功能)。还有一种用于HTML5和Javascript的OpenGL ES 2变体,称为WebGL。您可以找到教程here以及包含所有示例的ZIP文件;每当我需要检查我是否理解一个新概念时,我都会使用他们的代码库。
答案 1 :(得分:0)
因为你看起来很有趣:)
你在(1,1)到(-1,-1)// display()
中创建了一个红色方块然后说相机将使用正交投影// glOrtho来观察它 (它创建一个投影矩阵,使用一个点放置相机并给它一个方向)
通过glRotating MODEL * VIEW * 可能会有点倾斜PS你必须将gl命令视为发送到gl子系统的消息,这些消息会改变它的各种状态,场景中的内容,摄像机的位置,灯光的位置等等。