我有一个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;
}
Run Code Online (Sandbox Code Playgroud)
无论如何,我更愿意把它变成一种学习体验,所以请解释并链接到有用的东西!谢谢.
程序显示负责实际绘图.
void display()
{
Run Code Online (Sandbox Code Playgroud)
该行清除缓冲区 ; 缓冲区基本上是渲染图像的内存; 它基本上是一个宽度和高度为600x600的矩阵.到清除装置的矩阵的每个小区设置到相同的值.每个单元格都是一个像素,包含颜色和深度.通过这个调用,你告诉OpenGL绘制所有不透明的黑色,并将深度重置为1.为什么不透明的黑色?由于您调用glClearColor:前三个参数是红色,绿色和蓝色组件,它们的范围在0到1之间.0,0,0表示黑色.对于您指定的最后一个组件1,表示不透明; 0将是透明的.最后一个组件称为alpha,在启用Alpha混合时使用.为什么清晰的深度是1?因为1是默认值,并且您没有调用glClearDepth来覆盖该值.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Run Code Online (Sandbox Code Playgroud)
这告诉OpenGL您想要绘制四边形.
glBegin(GL_QUADS);
Run Code Online (Sandbox Code Playgroud)
您希望这些四边形为红色(请记住,颜色的第一个成分是红色).
glColor3f(1, 0, 0); // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK
Run Code Online (Sandbox Code Playgroud)
现在列出四边形的顶点(它只有一个,四个顶点); 所有顶点都是红色的,因为你永远不会通过调用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);
Run Code Online (Sandbox Code Playgroud)
这意味着您完成了绘图.
glEnd();
Run Code Online (Sandbox Code Playgroud)
从技术上讲,可能是OpenGL没有将您指定的任何命令发送到图形卡; 为了效率原因,可以将命令排队.调用glFlush会强制将命令发送到图形卡.
glFlush();
}
Run Code Online (Sandbox Code Playgroud)
你编写了这个函数,init来初始化一些OpenGL 状态,你觉得它们会在整个应用程序中保持稳定.实际上,像游戏这样的真实应用程序会显示大部分内容.例如,当玩家移动时,游戏必须不断更新相机.
void init()
{
Run Code Online (Sandbox Code Playgroud)
正如我们之前所说的那样,您将清晰的颜色设置为不透明的黑色.
glClearColor(0.0, 0.0, 0.0, 1.0);
Run Code Online (Sandbox Code Playgroud)
在这里你说的是相机不是透视类型; 基本上遥远的事情不会变小.它类似于人造卫星对城市的看法.特别是你正在创建一个不在视场"居中"的摄像头:我建议你使用像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?
Run Code Online (Sandbox Code Playgroud)
在这里,您基本上将相机相对于正方形或相对于相机的正方形定位; 有无限的方式来看待它.您正在定义一个几何变换,并且它被称为MODELVIEW的原因是它不是唯一改变模型(正方形)或视图(相机)的东西,而是两者,这取决于您看到的方式.但是,你的方块显示为旋转,因为你正在调用glRotatef ; 删除它,方块应该看起来像一个正方形.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(30.0, 1.0, 1.0, 1.0);
Run Code Online (Sandbox Code Playgroud)
深度测试是一种使用缓冲区中的深度存储以移除隐藏表面的技术,例如3D场景中立方体的背面.您的场景是2D,而您只绘制四边形,因此这不会影响您的绘图.
glEnable(GL_DEPTH_TEST);
}
Run Code Online (Sandbox Code Playgroud)
在主要的情况下,您正在与glut进行交互,这是一个可选的子系统,它不是OpenGL的一部分,但是可以执行一些只有操作系统被授权执行的枯燥乏味的操作.
int main(int argc, char *argv[])
{
Run Code Online (Sandbox Code Playgroud)
首先,你必须初步过剩.
glutInit(&argc, argv);
Run Code Online (Sandbox Code Playgroud)
然后定义将包含渲染图像的窗口.
glutInitWindowSize(600, 600);
glutInitWindowPosition(250, 250);
Run Code Online (Sandbox Code Playgroud)
GLUT_RGB表示您的窗口仅支持红色,绿色和蓝色,并且没有alpha通道(通常情况下).GLUT_DEPTH意味着您的缓冲区将能够存储每个像素的深度.GLUT_SINGLE意味着窗口是单缓冲的,即你的命令将直接在窗口上绘制; 另一个选项是双缓冲,你实际上在后缓冲区上绘制,然后你交换前后缓冲区,以便渲染的图像突然出现,而不是以渐进的方式.你的场景非常简单,你不应该注意到GLUT_SINGLE和GLUT_DOUBLE之间有任何区别.
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
Run Code Online (Sandbox Code Playgroud)
然后你实际上创建了窗口.
glutCreateWindow("Model View");
Run Code Online (Sandbox Code Playgroud)
你告诉我应该调用哪个函数来渲染场景.
glutDisplayFunc(display);
Run Code Online (Sandbox Code Playgroud)
在这里你可以调用你的init函数.
init();
Run Code Online (Sandbox Code Playgroud)
这是一个由过剩提供的窗口循环.大多数窗口系统需要一个软件循环才能使窗口保持活动状态,并能够响应点击,拖动,调整大小和键盘敲击.
glutMainLoop();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
简而言之,可以使用多种版本的OpenGL,它们可以使用多种语言进行编程,并针对多个平台.这些版本之间最重要的区别是有些使用固定功能管道(FFP),而最新版本有可编程管道.您的程序使用固定功能管道.你应该切换到一个可编程管线时,你可以,因为是做计算机图形学的现代的方式,而且是很多更灵活,即使它需要更多一点的节目,顾名思义.
你应该忽略我最初链接的教程,我没有立刻意识到它们过时了.您应该使用datenwolf推荐的那个,或者如果您对移动开发感兴趣,可以考虑学习OpenGL ES 2(2很重要,因为之前的版本是固定功能).还有一种用于HTML5和Javascript的OpenGL ES 2变体,称为WebGL.您可以在此处找到教程,以及包含所有示例的ZIP文件; 每当我需要检查我是否理解新概念时,我都会使用他们的代码库.
| 归档时间: |
|
| 查看次数: |
559 次 |
| 最近记录: |