1. 程式人生 > >第一個OpenGL程序

第一個OpenGL程序

個數 64位 每一個 至少 cti char 大寫字母 inf ctrl+c

一、OpenGL簡介

  • OpenGL基本函數庫用來描述圖元、屬性、幾何變換、觀察變換和進行多種其它操作。
  • OpenGL是一個開放式的、與硬件無關的軟件包。因此輸入和輸出函數等操作均不包含在其基本庫中。但在OpenGL開發的輔助庫中有輸入和輸出函數以及眾多附加函數。
  • OpenGL是一個專業的、功能強大的、調用方便的底層三維圖形函數庫。
  • OpenGL是一個圖形與硬件的接口。

二、OpenGl語法

OpenGl基本庫(核心庫)中的函數都要以gl為前綴。並把組成函數的每個單詞首字母用大寫形式表示。例如

glClear,glPolygonMode

OpenGL中的常量均以大寫字母GL開頭,命名中每一個組成單詞均大寫,中間用_隔開。例如

GL_RGB,GL_POLYGON

不同機器上整數描述範圍可能不同,OpenGL有專門的數據類型。如下

後綴 數據類型 典型的對應C語言類型 OpenGL類型定義
b 8位整數 signed char GLbyte
s 16位整數 short GLshort
i 32位整數 int or long GLint,GLsizei
f 32位浮點數 float GLfloat,GLclampf
d 64位浮點數 double GLdouble,GLclampd
ub 8位無符號整數 unsigned char GLubyte,GLboolean
us 16位無符號整數 unsigned short GLushort
ui 32位無符號整數 unsigned int or unsigned long GLuint,GLenum,GLbitfield

OpenGL的庫函數采用C語言風格,他們分別屬於以下不同的庫。

  • OpenGL核心庫,函數名前綴gl。
  • OpenGL實用庫,函數名前綴glu。
  • OpenGL輔助庫,函數名前綴aux。
  • OpenGL工具庫,函數名前綴glut。
  • Windows專用庫,函數名前綴wgl。
  • Win32 API 函數庫。

三、第一個OpenGL程序

首先一步步來創建我們的第一個OpenGL程序:在窗口中畫一條線段。我們使用GLUT

進行顯示窗口管理。當使用OpenGL實用庫時,首先要初始化GLUT,該初始化函數可以處理任何命令行變量,這裏先不使用命令行參數。

glutInit(&argc, argv);

接著創建一個窗口並給出標題。

gultCreateWindow("LearnOpenGL example");

盡管窗口有默認位置和大小,但是還可以使用glut函數來設置這些參數。例如

glutInitWindowPosition(50,100);

上面代碼指定顯示窗口左上角應在屏幕左邊界向右50個像素、屏幕上邊界向下100個像素。

glutInitWindonSize(800,600);

上面代碼指定寬度為800像素,高度為600像素的顯示窗口。還可以使用gultInitDisplayMode函數來顯示窗口和緩存和顏色模型。如下面使用單個緩存和RGB三原色組成的模型。

glutInitDisplayMode(GULT_SINGLE|GLUT_RGB);

可以使用RGB顏色設置顯示窗口的背景顏色。使用函數

glClearColor(1.0,1.0,1.0,0.0);

上面代碼將背景顏色設置為白色,四個參數是\(RGBA\),分別表示紅、綠、藍、以及調和參數,\(A=0.0\)表示完全透明,\(A=1.0\)表示完全不透明。這裏先不仔細討論這個參數。實驗中我們將背景顏色設置為類似於黑板的顏色。

盡管上述命令將顏色參數賦給了窗口,但是不能讓顯示窗口在屏幕上出現。還必須引入下面函數

glClear(GL_COLOR_BUFFER_BIT);

變量GL_COLOR_BUFFER_BIT是OpenGL常量,用它來指定顏色緩存的位值。除了顯示背景色,還可以為要顯示的場景中的數據顯示各種顏色。

glColor3f(0.0,0.4,0.2);

上面指定的三個分量就是RGB值。我們的第一個程序是顯示一條二維的線段,但是OpenGL是默認處理3維的,二維線段是三維的特例,但是OpenGL還是采用三維觀察來處理這個圖形。用函數

glMatrixMode(GL_PROJECTTION);
gluOrtho2D(0.0,200.0,0.0,150.0);

表示用正投影觀察將世界坐標系2維矩形區域映射到屏幕上,矩形區域上\(x\)範圍從\(0-200.0\),\(y\)範圍為\(0-150.0\)。完整程序

在OpenGL中,我們利用頂點來定義圖形系統可以識別的基本幾何圖元。OpenGL中許多函數都有多重形式,頂點函數的形式為glVertex*(),*號表示諸如nt、ntv之類的,\(n\)代表維數,\(t\)表示數據類型,\(v\)表示變量由指向一個數組的指針來給出。例如在2維坐標中畫一個點:glVertex2f(50.0f,100.0f);表示在二維坐標系中位置為\((50,100)\)處化一個點,點的數據類型是GLfloat,而下面形式用整數類型確定了三維空間的一個位置

glVertex3i(GLint x, GLint y,GLint z);

如果利用數組來表示三維點的信息GLint vertex[3];, 那麽可以使用

glVertex3iv(vertex);

頂點可以定義很多位置的幾何圖元。下面是在窗口中畫一條線段的完整程序。

#include <GL/glut.h>
#include <iostream>

using namespace std;

void lineSegment()
{
    // clear display-window
    glClear(GL_COLOR_BUFFER_BIT);
    // set linesegment color to red
    glColor3f(1.0, 0.0, 0.0);
   // Create linesigment
    glBegin(GL_LINES);
        glVertex2i(0, 0);
        glVertex2i(50, 500);
    glEnd();

    glFlush();
}

int main(int argc, char **argv)
{
    // Initialize GLUT
    glutInit(&argc, argv);
    // Set display model
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    // Set window position
    glutInitWindowPosition(100, 100);
    // Set Display window size
    glutInitWindowSize(800, 600);
    //create aw window
    glutCreateWindow("LearnOpenGL example");

    // ====================================================================
    // Set display-window color
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    // set projection parameters
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 200.0, 0.0, 200);

    // display line
    glutDisplayFunc(lineSegment);
    glutMainLoop();
    return 0;
}

OpenGL利用下面形式來定義幾何對象

glBegin(type);
    glVertex*();
    ...
    ...
    glVertex*();
glEnd();

參數type指定OpenGL把頂點組合起來定義幾何對象的方式。OpenGL提供了多種類型的點和線段圖元

  • 點(GL_POINTS) 每個頂點被顯示的大小至少是一個像素。
  • 線段(GL_LINES) 圖元把相繼的頂點配對後解釋為線段的兩個端點。註意頂點時兩兩配對處理的,所以如果有奇數個點,最後一個點由於無法配對,將會被舍棄。
  • 折線(GL_LINE_STRIP,GL_LINE_LOOP) 使用這兩個參數表示用線段將相鄰兩個點相連,而後者還將最後一個點與第一個點相連從而形成閉環。可以看經典教材《計算機圖形學(第四版)》的\(P_{39}\)頁更形象。

在繪制圖元時,在應用程序結束後,可能我們還沒來得及看到輸出窗口就消失了。目前可以使用GLUT函數

void glutMainLoop();

這個函數執行會讓程序進入一個事件處理循環。如果沒有事件需要處理,程序會處於等待狀態,直到通過某種外部方式來終止程序的執行,比如按下Ctrl+C。

圖形是通過一個稱為顯示回調(display callback)的函數發送到屏幕上的。這個函數通過下面的GLUT函數指定並註冊(register)到窗口系統:

void glutDisplayFunc(void (*func)(void));

只要窗口系統確定OpenGL窗口需要重新繪制,上面指定的func函數就會被調用。

四、動手實現二維Sierpinski鏤墊程序

Sierpinski鏤墊是一個有趣的圖形。我們先來嘗試繪制二維的Sierpinski鏤墊圖形,初始給出一個三角形ABC,步驟如下:

  1. 在三角形中隨機選擇一個初始點\(p(x,y)\).
  2. 隨機選擇三個頂點之一。
  3. 求點\(p\)與第二步中選擇的三角形頂點的中點並將該點畫出來。
  4. 更新該點為點\(p\)
  5. 轉步驟2

我們假定循環5000次,然後看看最終的效果是什麽。將主程序寫成函數display(),先給出代碼和效果,然後再對程序進行分析。

#include <GL/glut.h>
#include <iostream>
#include <cmath>
using namespace std;


void Init()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glColor3f(1.0, 0.0, 0.0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 100.0, 0.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
}

void Display()
{
    GLfloat vertices[3][2] = { {10.0,10.0},{90.0,10.0},{50.0, 70.0} };
    int i, j, k;
    GLfloat p[2] = { 75.0,75.0 };
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POINTS);
    for (int i = 0; i < 5000; i++)
    {
        int j = rand() % 3;
        p[0] = (vertices[j][0] + p[0]) / 2;
        p[1] = (vertices[j][1] + p[1]) / 2;
        glVertex2fv(p);
    }
    glEnd();
    glFlush();
}

int main(int argc, char **argv)
{
    // Initialize GLUT
    glutInit(&argc, argv);
    // Set display model
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    // Set window position
    glutInitWindowPosition(100, 100);
    // Set Display window size
    glutInitWindowSize(800, 600);
    //create aw window
    glutCreateWindow("LearnOpenGL example");

    // ====================================================================
    // Set display-window color
    
    // display Cycle
    glutDisplayFunc(Display);

    Init();
    glutMainLoop();

    return 0;
}

Init()函數包括了必要的初始化步驟。主要看display()函數,我們首先定義了三角形的三個頂點存放在vertices[]數組中,然後在三角形內部隨機選取了一個點p,接著就開始畫點了,循環5000次,這個過程中,我們使用了rand()函數來隨機選擇一個三角形的頂點。而最終顯示,這些點收斂的很有規律。
技術分享圖片

第一個OpenGL程序