现在的位置: 首页 > 综合 > 正文

[OpenGL]用OpenGL图形的绘制–矩形

2019年01月09日 ⁄ 综合 ⁄ 共 3137字 ⁄ 字号 评论关闭
/*在窗口的中心位置绘制一个矩形*/
#include <Windows.h>
#include <gl/glut.h>

//显示回调函数
void RenderScene()//用于在窗口中绘制需要的图形
{
    glClear(GL_COLOR_BUFFER_BIT);//用当前清除色清除颜色缓冲区,即设置窗口的背景色。一副图像的红,绿,蓝成分通常被并称为颜色缓冲区或像素缓冲区。1.实际清除
    glColor3f(1.0f,0.0f,0.0f);//设置当前绘图使用的RGB颜色。2.设置当前绘图颜色
    glRectf(100.0f,150.0f,150.0f,100.0f);//使用当前颜色绘制一个填充的矩形。3.图像绘制
    glFlush();//刷新OpenGL命令队列.4.刷新队列
    /*
    glFlush()用于让所有尚未执行的OpenGL命令都被执行。在内部,OpenGL使用一条渲染流水线来顺序处理命令。OpenGL命令和语言通常要排队,以便OpenGL驱动程序一次处理若干条"请求"。这种设置能提高性能,特别是在构造复杂对象的时候。GLFlush()只是告诉OpenGL,它应处理到目前为止收到的绘图命令,而不要等待更多的绘图命令。
    */
}

//再整形回调函数
void ChangeSize(GLsizei w,GLsizei h)//窗口大小改变时调用的登记函数
{
    if (h == 0)
    {
        h = 1;
    }
    glViewport(0,0,w,h);//设置视区尺寸

    //重置坐标系统,使投影变换复位
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //建立修剪空间的范围
    if (w <= h)
    {
        glOrtho(0.0f,250.f,0.0f,250.0f*h/w,1.0f,-1.0f);
    }
    else
    {
        glOrtho(0.0f,250.0f*w/h,0.0f,250.0f,1.0f,-1.0f);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
/*再整形回调函数
窗口在物理上是以像素来测量的。开始在窗口中绘图之前,必须告诉OpenGL如何把指定的坐标转换为屏幕坐标。为止,先指定窗口在笛卡尔空间中占据的区域,这一区域在计算机图形学中称为"窗口",这里为了与操作系统的窗口有所区别,我们称这一区域为"修剪区"。而以像素计算的话,修剪区的宽度和高度很少会恰好与窗口的宽度和高度一致。所以坐标系必须从逻辑笛卡尔坐标映射为物理屏幕的像素坐标。这种映射是有称为"视区"的设置指定的。视区是窗口的客户区内用于绘制修剪区的区域,即把修剪区映射为窗口的一个区域。通常把视区定义充满整个窗口。
当窗口的大小改变,ChangeSize()就会收到新的宽度和高度,在函数中利用这些信息可以完成修剪区到视区(坐标系到实际屏幕坐标)的映射。
void glViewport(GLint x,GLint y,GLsizei width,GLsizei height);
x和y参数指定窗口内视区的坐下角,width和height参数以像素为单位指定宽度和高度。通常,x和y都是0,但是可以用视区来渲染窗口不同区域中的多幅图形。
glOrtho()定义修剪区。这里需要注意一点,如果指定的视区不是正方形,而定义的修剪区是正方形,这样在完成修剪区到视区的映射后,显示的图形会发生变形,影响效果,为此必须保证定义的视区和修剪区的纵横比保持一致。
void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,DLdouble far);
该函数在3D笛卡尔坐标空间中定义了一个修剪空间,
left和right指定x轴上显示的最小和最大坐标值;
bottom和top则用于y轴;
near和far则用于z轴,通常是远离观察者的负值。
由于这个修剪空间要映射到视区,这种三维空间到二维的映射,需要利用投影来实现,这里使用的是正投影。故此在调用glOrtho()之前,调用了glMatrixMode(GL_PROJECTION);glLoadIdentity();这两个函数。
这两个函数定义了投影矩阵,投影矩阵是实际定义视区空间的地方,而glOrtho()并不是真正建立修剪空间,而是修剪现有的修剪空间,它用描述了其参数中说明的修剪空间的矩阵乘以描述当前修剪空间的矩阵,为了避免每次调用glOrtho()时对修剪空间造成进一步的破坏,所以使用glLoadIdentity()使坐标系"复位"。
ChangeSize()中最后glMatrixMode(GL_MODELVIEW);glLoadIdentity();这两个函数告诉OpenGL将来所有变换都会影响模型。
*/

//初始化
void SetupRC()//用于初始化,常用来设置场景渲染状态
{
    glClearColor(1.0f,1.0f,1.0f,1.0f);//设置窗口的清除色为白色
}
void main()
{
    glutInitDisplayMode(GLUT_SINGLE );//初始化glut库OpenGL窗口的显示模式
    glutCreateWindow("GLRect");//创建一个名为GLRect的窗口
    SetupRC();
    glutDisplayFunc(RenderScene);//设置当前窗口的显示回调函数
    glutReshapeFunc(ChangeSize);//设置当前窗口的再整形回调函数
    glutMainLoop();//启动主glut事件处理循环

    //流程:定义窗口->初始化设置->绘制场景->变换->运行结束。
}
/*
1.单缓冲区窗口(GLUT_SINGLE):由于在屏幕上显示图形是由像素构成的,而像素的颜色及灰度信息都是存储在帧缓冲区中,单缓冲区窗口使用单一的帧缓冲存储区,这样所有的绘图命令都在显示窗口中执行。
双缓冲区窗口(GLUT_DOUBLE):它使用了两个帧缓冲存储区,这样在窗口中执行的绘图命令实际上利用其中一个帧缓冲存储区创建一个场景,然后很快交换到窗口视图中来,这种方法常用于产生动画效果的场合。

2.回调函数
glutDisplayFunc(RenderScene);glutReshapeFunc(ChangeSize); 回调函数是响应某种事件而被调用的函数,他是由程序编写,通过GLUT注册函数连接到特定的函数。这样只要需要绘制窗口,glut就会调用函数RenderScene;而当窗口的大小或形状发生变化时,glut会调用函数ChangeSize。

3.设置上下文并执行
SetupRC()与glut框架无关,其作用是进行OpenGL的初始化。
OpenGL的初始化必须在渲染之前进行,由于OpenGL使用状态机,即每条OpenGL命令都使用当前的渲染状态完成,而对当前渲染状态的任何修改都会影响到之后的任何OpenGL命令,直至再次修改当前渲染状态,故在一个场景中,许多的状态只要设置一次就可以了。
glutMainLoop();让glut框架开始运行,所有设置的回调函数开始工作,直到用户终止程序为止。

4.由上面的程序可以看出,一个OpenGL程序的基本结构主要包括以下几个部分
A.定义窗口:包括制定窗口的大小,为止,显示模式已经设置各种回调函数
B.初始化设置:清除各种缓冲区,并设置各种OpenGL状态,例如设置背景色,打开光照,设置纹理等等
C.绘制场景:利用OpenGL函数绘制场景中的各种物体
D.变换:指定场景中需要显示的范围并指定由剪裁区到视区的变换。
E.结束运行:清楚明了缓冲区,执行OpenGL命令。
*/

效果图:

抱歉!评论已关闭.