1. 程式人生 > >OpenGL程式設計(三)讓矩形動起來

OpenGL程式設計(三)讓矩形動起來

上次實現了在視窗中新增一個了一個矩形。這次的任務是在上次程式碼的基礎上,讓那個矩形動起來。

1、思路
要看到動態的效果,首先新增一個定時器,規定的時間重新整理一次視窗;不斷修改矩形的位置,使其在時間軸上達到動態的效果。

2、註冊定時器
glutTimerFunc(33, timerFunction, 1); 33表示33毫秒後呼叫,timerFunction為回撥函式,1為區別值(用以區分不同的定時器)。然後我們在timerFunction函式裡修改矩形的座標。因為註冊一次定時器(glutTimerFunc)才會回撥一次,所以要達到持續的效果,在timerFunction函式體內的末尾再是註冊定時器回撥自己glutTimerFunc(33, timerFunction, 1);

3、在定時器回撥函式體內修改矩形的位置
假設矩形的左下角的位置為(x1, y1),每次回撥我們修改x1,y1的值,讓x1,y1加上或減去一個步長(向左運動是加,向右運動是減;向上運動是加,向下運動是減)。當x1的值大於等於視窗的寬度減去矩形的長(x1 > windowWidth - size)時x1開始改方向為減去步長x1 -= xstep;;當x1的值小於0時x1再次改為反方向為加步長(x1 += xstep;);同理y1也使用同樣的方法處理。

4、重繪視窗
glutPostRedisplay();每次修改矩形的位置時要呼叫該函式重繪視窗。該函式的呼叫不是馬上讓GULT馬上重繪視窗,而是先告訴GULT視窗已經改變,需要重新繪畫,等GULT再次呼叫glutMainLoop()函式時會重回視窗,以達到視窗改變的效果。

完整程式碼如下:

#include <windows.h>
#include <gl/glut.h>

//animation.cpp

GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei size = 50;

GLfloat xstep = 5.0f;
GLfloat ystep = 5.0f;

GLfloat windowWidth = 300.0f;
GLfloat windowHeight = 300.0f;

void renderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT);   //清空顏色緩衝池
glColor3f(1.0f, 0.0f, 0.0f); //設定繪圖顏色 glRectf(x1, y1, x1 + size, y1 + size); //繪製矩形 glFlush(); //執行OpenGL指令列表中的指令 } void timerFunction(int value) { if(x1 > windowWidth - size || x1 < 0) xstep = -xstep; if(y1 > windowWidth - size || y1 < 0) ystep = -ystep; if(x1 > windowWidth - size) x1 = windowWidth - size - 1; if(y1 > windowHeight - size) y1 = windowHeight - size - 1; x1 += xstep; y1 += ystep; glutPostRedisplay(); glutTimerFunc(33, timerFunction, 1); } void main(void) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //設定顯示模式 glutInitWindowSize(windowWidth, windowHeight); //設定視窗大小 glutInitWindowPosition(200, 200); //設定視窗在螢幕上的位置 glutCreateWindow("動畫"); //建立視窗並給出標題 glutDisplayFunc(renderScene); //註冊顯示視窗時回撥函式renderScene glOrtho(0.0f, windowWidth, 0.0f, windowHeight, 1.0, -1.0); //修改修剪空間的範圍 glutTimerFunc(33, timerFunction, 1); //註冊定時器 glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //使用藍色清空背景底 glutMainLoop(); //訊息迴圈(處理作業系統等的訊息,例如鍵盤、滑鼠事件等) }

5、讓動畫看起來更順暢
上面能看到了動畫的效果,但是有時候看起來不是很順暢,主要原因是上面使用的是單緩衝的技術(前面文章提到過),即在顯示視窗執行繪圖過程。應該把單緩衝改為雙緩衝,即現在顯示視窗外完成了繪圖,然後再把已經渲染完成的繪圖切換到顯示視窗。要修改的地方有:glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 把GLUT_SINGLE改成GLUT_DOUBLE。同時把glFlush();改成glutSwapBuffers();

完整程式碼如下:

#include <windows.h>
#include <gl/glut.h>

//animation.cpp

GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei size = 50;

GLfloat xstep = 5.0f;
GLfloat ystep = 5.0f;

GLfloat windowWidth = 300.0f;
GLfloat windowHeight = 300.0f;

void renderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT);   //清空顏色緩衝池
    glColor3f(1.0f, 0.0f, 0.0f);    //設定繪圖顏色
    glRectf(x1, y1, x1 + size, y1 + size);    //繪製矩形
    glutSwapBuffers();
}

void timerFunction(int value)
{
    if(x1 > windowWidth - size || x1 < 0)
        xstep = -xstep;

    if(y1 > windowWidth - size || y1 < 0)
        ystep = -ystep;

    if(x1 > windowWidth - size)
        x1 = windowWidth - size - 1;

    if(y1 > windowHeight - size)
        y1 = windowHeight - size - 1;

    x1 += xstep;
    y1 += ystep;

    glutPostRedisplay();
    glutTimerFunc(33, timerFunction, 1);
}

void main(void)
{
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);    //設定顯示模式
    glutInitWindowSize(windowWidth, windowHeight); //設定視窗大小
    glutInitWindowPosition(200, 200);   //設定視窗在螢幕上的位置 
    glutCreateWindow("動畫"); //建立視窗並給出標題
    glutDisplayFunc(renderScene);   //註冊顯示視窗時回撥函式renderScene
    glOrtho(0.0f, windowWidth, 0.0f, windowHeight, 1.0, -1.0);  //修改修剪空間的範圍
    glutTimerFunc(33, timerFunction, 1);    //註冊定時器
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);   //使用藍色清空背景底
    glutMainLoop();     //訊息迴圈(處理作業系統等的訊息,例如鍵盤、滑鼠事件等)
}

6、效果
這裡寫圖片描述