1. 程式人生 > >OpenGL進階(一)

OpenGL進階(一)

提要

OpenGL視口(Viewport)可以看作是視窗中OpenGL的繪製輸出區域,可以通過一條簡單的glViewport命令設定。一般的OpenGL教程都是單視口,即整個視窗為惟一的一個視口,Nehe的OpenGL教程是我最早見到涉及多視口的。與單視口程式相比,多視口程式的變化主要是:

(一)多視口程式不能在視窗resize/reshape時直接呼叫glViewport,而應該在此時記下視窗大小,然後在繪製場景時多次呼叫glViewport設定每個視口的位置和大小;

(二)對於每個視口,應分別呼叫glMatrixMode(GL_PROJECTION)和glMatrixMode(GL_MODELVIEW)以設定投影和建模矩陣。

多視口的最常見的應用,就是3DMax中的多視口建模,每一個觀察口都從不同的方向去觀察模型,從而很方便地去獲取模型當前的狀態。

還有就是賽車遊戲中的後視鏡等等.

具體實現的思路就是對每個視口進行獨立的渲染。

函式解析

下面是需要呼叫到的一些OpenGL的函式。

glLoadIdentity()

重置當前指定的矩陣為單位矩陣.

glViewport(GLint x,GLint y,GLsizei width,GLsizei height)

在視窗中定義一個畫素矩形,最終將影象對映到這個矩形中。

void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)

建立了一個可視的二位平面區域。這個和用glOrtho函式的當near=0,far=1時效果是一樣。

void gluPerspective(GLdouble fovy, GLdouble aspect,GLdouble zNear,GLdouble zFar)

這個函式指定了觀察的視景體(frustum為錐臺的意思,通常譯為視景體)在世界座標系中的具體大小,一般而言,其中的引數aspect應該與視窗的寬高比大小相同。

void glScissor(GLint x,GLint y,GLsizei width,GLsizei height)

設定一個裁剪視窗,前兩個引數為視窗左下角位置,後兩個引數是視窗的寬度和高度。

使用前一定要glEnable(GL_SCISSOR_TEST);

程式碼實現

實現一:

void renderGL()
{
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();					                // 重置模型觀察矩陣

    for (int loop=0; loop<4; loop++)					// 迴圈繪製4個視口
    {
        if (loop==0)									// 繪製左上角的視口
        {
            // 設定視口區域
            glViewport (0, window_height/2, window_width/2, window_height/2);
            glMatrixMode (GL_PROJECTION);
            glLoadIdentity ();
            gluOrtho2D(0, window_width/2, window_height/2, 0);
        }
        if (loop==1)									// 繪製右上角視口
        {

            glViewport (window_width/2, window_height/2, window_width/2, window_height/2);
            glMatrixMode (GL_PROJECTION);
            glLoadIdentity ();
            gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );
        }
        if (loop==2)									// 繪製右下角視口
        {
            glViewport (window_width/2, 0, window_width/2, window_height/2);
            glMatrixMode (GL_PROJECTION);
            glLoadIdentity ();
            gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );
        }
        if (loop==3)									// 繪製左下角視口
        {
            glViewport (0, 0, window_width/2, window_height/2);
            glMatrixMode (GL_PROJECTION);
            glLoadIdentity ();
            gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );
        }
        glMatrixMode (GL_MODELVIEW);							
        glLoadIdentity ();

        glClear (GL_DEPTH_BUFFER_BIT);
        if (loop==0)									// 繪製左上角的檢視
        {
            glBegin(GL_QUADS);
            glColor3f(1.0f,0.0f,0.0f);			    // 設定當前色為紅色
            glVertex2i(window_width/2, 0              );
            glColor3f(0.0f,1.0f,0.0f);			    // 設定當前色為綠色
            glVertex2i(0,              0              );
            glColor3f(0.0f,1.0f,1.0f);			    // 設定當前色為藍色
            glVertex2i(0, window_height/2);
            glColor3f(1.0f,1.0f,0.0f);			    // 設定當前色為紅色
            glVertex2i(window_width/2, window_height/2);
            glEnd();
        }
        if (loop==1)									// 繪製右上角的檢視
        {
            glColor3f(1.0f,0.0f,1.0f);	
            glTranslatef(0.0f,0.0f,-9.0f);
            glRotatef(rtri,1.0,1.0,0.0);

            glBegin(GL_TRIANGLES);					    // 繪製三角形
            glVertex3f( 0.0f, 1.0f, 0.0f);			// 上頂點
            glVertex3f(-1.0f,-1.0f, 0.0f);			// 左下
            glVertex3f( 1.0f,-1.0f, 0.0f);			// 右下
            glEnd();						            // 三角形繪製結束

        }
        if (loop==2)									// 繪製右下角的檢視
        {
            glTranslatef(0.0f,0.0f,-2.0f);
            glRotatef(-45.0f,1.0f,0.0f,0.0f);
            glRotatef(rtri,0.0f,0.0f,1.0f);

            glBegin(GL_QUADS);
            glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);
            glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.5f,  0.5f, 0.0f);
            glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);
            glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);
            glEnd();

        }
        if (loop==3)									// 繪製左下角的檢視
        {
            glColor3f(0.0f,0.0f,0.0f);
            glTranslatef(0.0f,0.0f,-4.0f);
            glRotatef(-rtri/2,1.0f,0.0f,0.0f);
            glRotatef(-rtri/2,0.0f,1.0f,0.0f);
            glRotatef(-rquad/2,0.0f,0.0f,1.0f);

            glBegin(GL_QUADS);
            glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);
            glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.3f,  0.5f, 0.0f);
            glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);
            glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);
            glEnd();
        }
    }
    rtri+=0.2f;						                  // 旋轉變數
    rquad-=0.15f;						              // 旋轉變數
    SDL_GL_SwapBuffers( );
}

效果:


實現二:

void renderGL2()
{	

    //視口一  左下角
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,0,window_width/2-1,window_height/2-1);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);

    glViewport(0,0,window_width/2-1,window_height/2-1);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //繪製部分				
    glTranslatef(0.0f  ,0.0f  ,-5.0f  );  
    glRotatef(rtri,0.0f  ,1.0f  ,0.0f  );  
     //繪製一個三角錐  
    glBegin( GL_TRIANGLE_STRIP );  
    glColor3f( 1.0, 0.0, 0.0 );  
    glVertex3f(  0.0,  1.0,  0.0 );  
    glColor3f( 0.0, 1.0, 0.0 );  
    glVertex3f(-1.0, -1.0,  1.0 );  
    glColor3f( 0.0, 0.0, 1.0 );  
    glVertex3f(  1.0, -1.0,  1.0 );  
    glColor3f( 0.0, 1.0, 0.0 );  
    glVertex3f(  1.0, -1.0, -1.0 );  
    glColor3f( 1.0, 0.0, 0.0 );  
    glVertex3f(  0.0,  1.0,  0.0 );  
    glColor3f( 0.0, 1.0, 0.0 );  
    glVertex3f(-1.0, -1.0,  1.0 );  
    glEnd();  

    //視口二 左上角
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,window_height/2+1,window_width/2-1,window_height/2-1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);

    glViewport(0,window_height/2+1,	window_width/2-1,	window_height/2-1);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //繪製部分
    glColor3f(1.0f,0.0f,1.0f);
    glTranslatef(0.0f,0.0f,-9.0f);
    glRotatef(rtri,1.0,1.0,0.0);

    glBegin(GL_TRIANGLES);					    // 繪製三角形
    glVertex3f( 0.0f, 1.0f, 0.0f);			// 上頂點
    glVertex3f(-1.0f,-1.0f, 0.0f);			// 左下
    glVertex3f( 1.0f,-1.0f, 0.0f);			// 右下
    glEnd();						            // 三角形繪製結束

    //視口三  右下角
    glEnable(GL_SCISSOR_TEST);
    glScissor(window_width/2+1,	0,	window_width/2-1,	window_height/2-1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);

    glViewport(window_width/2+1,0,window_width/2-1,	window_height/2-1);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //繪製部分
    glTranslatef(0.0f,0.0f,-2.0f);
    glRotatef(-45.0f,1.0f,0.0f,0.0f);
    glRotatef(rtri,0.0f,0.0f,1.0f);

    glBegin(GL_QUADS);
    glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);
    glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.5f,  0.5f, 0.0f);
    glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);
    glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);
    glEnd();

    //視口四  右上角
    glEnable(GL_SCISSOR_TEST);

    glScissor(window_width/2+1,	window_height/2+1, window_width/2-1, window_height/2-1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);

    glViewport(window_width/2+1,	window_height/2+1, window_width/2-1, window_height/2-1);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //繪製部分
    glColor3f(0.0f,0.0f,0.0f);
    glTranslatef(0.0f,0.0f,-4.0f);
    glRotatef(-rtri/2,1.0f,0.0f,0.0f);
    glRotatef(-rtri/2,0.0f,1.0f,0.0f);
    glRotatef(-rquad/2,0.0f,0.0f,1.0f);

    glBegin(GL_QUADS);
    glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);
    glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.3f,  0.5f, 0.0f);
    glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);
    glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);
    glEnd();
    rtri+=0.2f;						                  // 旋轉變數
    rquad-=0.15f;						              // 旋轉變數
    SDL_GL_SwapBuffers( );
}
void initGL( int width, int height )
{
    float ratio = (float) width / (float) height;
    // Our shading model--Gouraud (smooth). 
    glShadeModel( GL_SMOOTH );
    // Set the clear color. 
    glClearColor( 0, 0, 0, 0 );
    // Setup our viewport. 
    glViewport( 0, 0, width, height );
    //Change to the projection matrix and set our viewing volume.
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0, ratio, 1.0, 100.0 );
}



參考:OpenGL中的多視口-