[OpenGL]利用OpenGL绘制一些简单的图形

在几何学中有点,线,边,图形的概念,这些概念在计算机中也存在,但是可能会有所不同,比如数学中的直线是表示两端无限延伸的一条线,并且在数学中直线是没有宽度的,但是计算机中无法做到无限延伸,可以说计算机中的直线概念更像是数学中的线段概念,两个点的相连。同样点也是一样,数学中的点是表示一个坐标,并没有大小。计算机中无论图形设备多么精密也做不到显示一个无穷小的点,一般不设置点的大小的画,计算机会把点显示为1像素大小。在OpenGL中规定,一个多边形必须是一个“凸多边形”(多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的)。多边形可以由其边的顶点来确定。
好了,通过了解这些概念,我们可以利用点,线,多边形通过一些数学运算构成各种几何图形。


在OpenGL中确定点

在上高中的时候,数学老师在讲几何基础的时候说过,点连成线,线移动成面。可以说点是所有几何图形的基础。在OpenGL中为我们提供了一系列函数来指定点,他们都是以glVertex开头,后面的数字表示参数,f,d等表示数据类型(有编程的应该都会清楚)。v结尾的函数参数是指针。OpenGL和C/C++不同的是,OpenGL中是没有定义sting和char类型(或者说是没有必要用)的,因为这些类型在图形中是没有意义的。还有int型在OpenGL中将这个类型定义为GLint和GLsizei;float型在OpenGL中将这个类型定义为GLfloat和GLclampf;double型在OpenGL中将这个类型定义为GLdouble和GLclampd。这些函数虽然参数类型和个数不同,但是却可以表示相同的功能,如下面几行代码的功能是一样的:

    glVertex2i(1, 3);
    glVertex2f(1.0f, 3.0f);
    glVertex3f(1.0f, 3.0f, 0.0f);
    glVertex4f(1.0f, 3.0f, 0.0f, 1.0f);
    GLfloat VertexArr3[] = {1.0f, 3.0f, 0.0f};
    glVertex3fv(VertexArr3);

开始具体的绘制

我们知道如何确定顶点了,但是我们该如何约束这些点的行为呢?我们是要连成一条线,或者绘制一个多边形?OpenGL为我们提供了glBengin方法。OpenGL规定:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略)。并由glBegin来指明如何使用这些点。例如:

    glBegin(GL_POINTS);//指定这些顶点的行为为GL_POINTS
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.5f, 0.0f);
    glEnd();

这样会把这两个顶点显示出来,可以同过glPointSize方法来指定点的大小,如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。另外OpenGL还为我们提供了其他的参数来画出其他的集合图形,这里不作介绍。

绘制坐标轴

在上中学的时候,我们大多的集合图形都是画在坐标系中,这里我们先显示一个坐标系,原点为屏幕中点。代码如下:

int const WINWEIGHT=400;
int const WINHEIGHT=400;


void drawSomething(){
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //画线
    glLineWidth(1.0f);//设置线的宽度
    glBegin(GL_LINES);

        glVertex2f(0.0f,-1.0f);
        glVertex2f(0.0f,1.0f);//这两个点确定Y轴
        glVertex2f(1.0f,0.0f);
        glVertex2f(-1.0f,0.0f);//这两个点确定X轴
    glEnd();

    glFlush();

}

void InitializeCallback(){
    glutDisplayFunc(drawSomething);
    glutIdleFunc(drawSomething);
}
int _tmain(int argc, char* argv[])
{

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);//设置单缓冲
    glutInitWindowSize(WINWEIGHT,WINHEIGHT);//设置窗体大小
    glutInitWindowPosition(10,10);//设置窗体位置
    glutCreateWindow("DrawSomething");

    GLenum res=glewInit();

    if(res!=GLEW_OK){
        fprintf(stderr,"Error:%s",glewGetErrorString(res));
        return 1;
    }
    InitializeCallback();
    glClearColor(1.0f,0.0f,0.0f,0.0f);//窗体填充颜色为红色


    glutMainLoop();

    return 0;
}

我们会得到如下的显示:
[OpenGL]利用OpenGL绘制一些简单的图形_第1张图片
我们来看drawSomething函数(下面的绘图只需改变这个函数),我们在这个函数中进行绘制操作。OpenGL把glVertex*函数的参数限制在[-1,1](可以做修改,不做解释)。我们确定了4个点,在glBegin中传入GL_LINES表示把点两两相连。这样就画出了坐标系。

画一个圆形

画圆的方法应很多,这里就用最容易理解的一种方式。圆是什么?圆形就是有无穷多个边的多边形。边数越多,这个多边形就越接近圆。

#include

void drawSomething(){
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //画圆
    //圆上的各个点的坐标可以表示为(R*cos(x),R*sin(x));
    //所以可以用多边形表示圆,当边数足够多,那么就越接近圆
    const GLint n=100;//点数
    const GLfloat R=0.5f;//半径
    const GLfloat PI=3.1415926f;
    glPointSize(3.0f);
    //表示画出图形的模式.
    //GL_LINES会把点1和点2,点3和点4依次类推连接起来,要指定glLineWidt,点数足够多的情况下会画出一个虚边圆或者实边圆
    //GL_LINE_LOOP会画出一个未被填充的图形,只有边缘,要指定glLineWidt;
    //GL_POLYGON会画出一个填充的多边形
    //GL_POINTS只显示点
    glBegin(GL_LINE_LOOP);
        glColor3f(0.0f,0.0f,0.0f);//指定线条为黑色
        for(int i=0;icos(2*PI/n*i),R*sin(2*PI/n*i));
        }
    glEnd();
    glFlush();

上面声明的变量n是指点数,事实上我们可以通过改变n的值来画出不同的多边形,如:n=3的时候会画出一个正三角形。为4的时候是正方形。还有一点要特别注意,由于glVertex*函数参数被限制在[-1.0,1.0]之间,所以可以理解为这里的参数是表示占的窗口的比例。如同我们上面画的坐标系,OpenGL把窗口分成了四个象限。这就造成了一个问题,我们这里把窗口设置为长宽比例为1:1,如果不是这个值的画,那么画出来的就会是一个椭圆,至于怎么解决还需要更深的学习。总之上面代码的运行结果入下:
[OpenGL]利用OpenGL绘制一些简单的图形_第2张图片

画五角星

其实画五角星一般都会确认五个点,然后连接起来。关于如何确定点,不同人有不同的方法。这里我是假设五角星对应的正五边形的边长为R,然后通过三角函数来确定点的,这里不做详解,相信有初中数学基础的应该都会推算出来。

#include



void drawSomething(){
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //画五角星
    const GLfloat R=0.5f;
    const int n=5;
    const GLfloat PI=3.1415926f;
    GLfloat Point[][5]={
        {R*cos(2*PI/n*0),R*sin(2*PI/n*0)},
        {R*cos(2*PI/n*1),R*sin(2*PI/n*1)},
        {R*cos(2*PI/n*2),R*sin(2*PI/n*2)},
        {R*cos(2*PI/n*3),R*sin(2*PI/n*3)},
        {R*cos(2*PI/n*4),R*sin(2*PI/n*4)}
    };
    //glPointSize(2.0f);
    glBegin(GL_LINE_LOOP);
        glVertex2fv(Point[0]);
        glVertex2fv(Point[2]);
        glVertex2fv(Point[4]);
        glVertex2fv(Point[1]);
        glVertex2fv(Point[3]);



    glEnd();
    glFlush();

}

显示如下:
[OpenGL]利用OpenGL绘制一些简单的图形_第3张图片

画正弦函数

这个就简单了,不过就是注意一下,把坐标的比例缩小一下就行了

#include 

void DrawSomething(GLvoid){
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glLineWidth(1.0f);
    glBegin(GL_LINES);
        glVertex2f(-1.0f,0.0f);
        glVertex2f(1.0f,0.0f);
        glVertex2f(0.0f,1.0f);
        glVertex2f(0.0f,-1.0f);
    glEnd();


    const GLfloat R=100.0f;

    glBegin(GL_LINE_STRIP);
        for (GLfloat i=-R;isin(i/5));
        }
    glEnd();

    glFlush();
}

[OpenGL]利用OpenGL绘制一些简单的图形_第4张图片

你可能感兴趣的:(OpenGL)