【GISER && Painter】Chapter00:OpenGL原理學習筆記

 說明:簡單瞭解一下OpenGL的工作原理,初步認識計算機對於圖形渲染的底層設計與實現,第一次接觸,也沒學過C艹,歡迎各位批評指正。

一  什麼是OpenGL?

OpenGL是一個開放標準(specification),是一種接口規範,並沒有固定實現。每個硬件廠商負責對自己的硬件提供OpenGL接口標準的具體實現。三者關係如下鏈表:OpenGL API---硬件廠商【各自完成具體實現接口】--使用者【調用OpenGL提供的接口】【廠商的第三方庫並不開源,但目前已有開源GL實現的DEMO,如Mesa,有興趣可自行了解。】

  在日常使用OpenGL時,需要的一些輔助第三方庫:GLUT,輔助實現窗口顯示、控制流程等功能,而OpenGL僅僅承擔圖形渲染的工作,即具體利用視圖變換、光照以及紋理着色等技術,還原實現了虛擬場景:

 實例1

 

實例2

二  OpenGL中不得不提的圖形渲染管線(Pipeline

  圖形渲染管線(Pipeline)可以看做是一條像素生產流水線,【流水線的輸入端是頂點數據和像素數據,經過光柵化後,將片元(Fragment)組合着色成爲屏幕可視內容,實現渲染效果】,

  -  固定的圖形管線渲染流程如下:

  1 )指定需要完成渲染的幾何圖元:這些幾何圖元均是通過頂點指定的,其中包括了點、直線以及三角形等幾何要素。

 

  2) 頂點變換操作:在獲得了指定圖元后,就可以對定義圖元的頂點進行變換處理。

 

  3 )裁剪、透視觸發以及視點適應變換等:將各個頂點進行變換處理後,需要將世界座標中的圖元規範化處理,統一縮放到正規化可視空間CCV中,圖元座標將會從世界座標轉換爲窗口座標;

  2/3這一套處理方式可以從圖形渲染管線的主幹中分出一個頂點渲染管線分支,該分支將在下一節詳細介紹。

 

  4 )光柵化【1】:座標變換,幾何離散化,即將圖元從三維座標轉換爲一個二維平面圖像。

 

  5 )片元處理操作:對光柵化後的片元圖像進行綜合處理:提取紋理、效果、顏色等,對片元進行逐個測試,如像素所有權、剪切、模版測試以及深度測試等,只有當所有測試都通過之後,纔會寫入幀緩衝區(Frame Buffer)【2】

 

  6) 片元數據轉換爲像素數據形式,寫入幀緩衝區

圖1 OpenGL的圖形渲染管線【3】

三  固定管線中的核心——頂點處理管線

  在圖像渲染管線中細分出的頂點處理管線主要用於對頂點數據進行降維轉換,即將三維空間中的實點轉換到二維空間屏幕的座標系上

  1)數學基礎

    在頂點處理管線中,最重要的一個概念在於變換,即上面概念提到的實點的空間轉換。但在詳細解釋頂點處理管線中的空間轉換前,我們需要簡單瞭解一下所需的數學基礎:齊次座標 和 矩陣與圖形變換

    -  座標:本質上是一個增加維度的操作,即n維向量(p1,p2,p3,…,pn)增加至第n+1維(p1,p2,p3…,pn,pn+1),方便空間變換中的旋轉、平移、透視等操作。

    -  矩陣與座標變換:圖形是由一個個座標點組成的,通過矩陣與轉換矩陣相乘,得到變換後的座標,即得到了空間變換後的圖形。

    舉一個簡單的例子:

    平移操作:設某幾何圖形的三維點座標集合爲{ (x,y,z) | x , y , z∈R},先要將圖形整體平移(a, b , c),首先,需要將三維點座標拓展爲齊次座標(x,y,z,1),其次,構造一個4*4的矩陣T:

圖2 平移單位矩陣T

    所以,平移操作可以視爲:(x,y,z,1)·T = (x+a, y+b, z+c, 1),所以該幾何圖形經過平移後的三維點座標集合爲{ (x+a, y+b, z+c) | x , y , z∈R}

     

 

  2)頂點處理管線主要步驟

    2-1)模型視圖變換:

① 模型變換主要包括了位移旋轉縮放仿射變換【4】,這個部分的模型變換比較簡單,上文也提到了關於平移操作的具體矩陣,所以在此就不贅述。模型變換中涉及到的變換大都是仿射變換,僅通過目標幾何體的齊次座標矩陣與操作單位矩陣點乘即可得到變換位置後的幾何體。

上述三個仿射變換操作,在OpenGL中分別對應着:glTranslate*(), glRotate*(), glScale*()

       

圖3 仿射變換

② 視圖變換

主要目的在於將目標幾何體從世界座標中移至攝像機座標,該變換主要圍繞“攝像機”的概念進行定義和實現:

首先,我們以攝像機作爲視點,將視點移動到當前座標系中的任一固定位置,並以此位置爲攝像機座標系的原點。若要將已處在世界座標系上的幾何體轉換到攝像機的座標體系中,則需要先得到攝像機座標系與世界座標系的相對關係,然後在從世界座標系中取得幾何體,並對該目標幾何體做出相應的相對關係處理。

       在OpenGL中提供了接口:gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz)

 

    2-2)光和顏色:

① 光照:

着色需要考慮光照反射光的情況,可以從單點光照模型的情況入手:

光照模型中,我們所能看到的光主要以目標物的反射光爲主,先不考慮入射光(有色OR無色)情況,反射光由鏡面反射和漫反射組成,除了鏡反射光IJ、漫反射光IM外,考慮到外部環境影響,設置環境光爲IE,環境反射光=環境光IE*環境反射係數pe。按照聚光燈模型,反射光IReturn會隨着角度和距離的變化而衰減,所以:IReturn=(IJ+IM+IE*pe)*atten(光源到幾何體面上某點的距離D)*衰減係數cos(β),再加上全局環境光IE_ALL與自發光e,總體反射光爲:

IReturnAll = IReturn + IE_ALL*pe + e

           在OpenGL中,最多可以定義8個光源,每個光源可以設置不同的屬性:  

      -  定義光源:Void glLight*(Glenum light, Glenum pname, GLfloat param)

            【light】對應光源

            【pname】參數字段

            【param】參數值

      其中pname可用參數參照下表:

GL_AMBIENT

環境光分量

GL_DIFFUSE

漫反射分量

GL_SPECULAR

鏡面反射分量

GL_POSITION

光照位置

GL_SPOT_CUTOFF

聚光燈角度

GL_SPOT_DIRECTION

聚光燈方向向量

GL_SPOT_EXPONENT

比例係數e

GL_CONSTANT_ATTENUATION

聚光燈衰減係數

GL_LINEAR_ATTENUATION

聚光燈衰減係數

GL_QUADRATIC_ATTENUATION

聚光燈衰減係數

 

     - 激活光源(默認不可用):glEnable(glLight*)

     - 定義目標物的表皮材質:void glMaterialf( GLenum face, Glenum pname, Gfloat param)

 

    ② 上色:

OpenGL一般有兩種着色模型:平面着色( Flat shading )和平滑着色( Smooth Shading),從效果來看,平滑着色在細節表現上要優於平面着色。而平滑着色又分爲Gouraud着色和Phong着色,其中Gouraud着色採用了線性插值的淡化邊方法,每個像素的顏色值都是通過線性插值的方式得到的,可以平滑的表達色彩和光照的過渡,但缺點在於不善於表達強光區。而Phong則是對法向量進行着色,當前OpenGL不支持該着色模型,即無法進行透視投影變換等後續操作。

     在OpenGL中:

      - 設置OpenGL着色模式的函數:

      void glShadeModel(GL_SMOOTH/GL_FLAT)

      - 提供瞭如下API接口以供顏色繪製:

      void glColor3f( GLfloat red, GLfloat green, GLfloat blue)

      void glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)

      (該着色過程發生在模型視圖變換之後)

      - 顏色清除API:

      void glClearColor(GLfloat , GLfloat , GLfloat, GLfloat )  //用於指定空色

      void glClear(GL_COLOR_BUFFER_BIT)    //空色填充,清除畫板 

    PS:值得一提的是,OpenGL3.0後均採用GLSL語言進行可編程渲染,通過着色器替代頂點處理管線、紋理化和色彩化環節【5】。着色器技術的可編程性可以實現各種圖像效果而不受顯卡固定管線的限制,提高了圖像的畫質。

    2-3)投影變換(Porjection):

在完成了上述的視圖模型變換之後,我們已經將幾何體從世界座標中轉換到了攝像機座標系中,接下來,爲了在二維平面上表示該幾何體,我們需要繼續進行下一個步驟——投影變換。投影變換可以簡單地理解爲,將三維空間的幾何體投影到攝像機視錐體的近平面和遠平面之間。一般投影變換可以分爲透視投影、正交投影和斜投影(本文以透視投影爲例)。

 

圖4 透視投影和平面投影(近裁面和遠裁面之間的空間稱之爲frustum)【6】

    透視投影遵循近大遠小的原理,符合人們日常的視覺心理,具有較好的仿真性。在OpenGL中也提供了兩個API接口:

    -   void glFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) 創建一個透視投影矩陣

      【left/right, bottom/top, -near】左下角點( left, bottom, -near)和右上角點( right, top, near)

      【far】遠裁面的Z值(負數)

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

      【fovy】x-z平面的視角張角的範圍

      【aspect】實際窗口的長寬比x/y

      【zNear】視錐體的近裁面

      【zFar】視錐體的遠裁面

    2-4)裁剪、透視除法(clip)

          經過上述處理,如果點位於Frustum的空間中,則投影變換後的幾何體點座標均介於[-1,1]之間,並將x∈[-1,1], y∈[-1,1], z∈[-1,1]的正方體定義爲正規化可視空間CCV,裁剪的目的在於裁剪掉CCV外的圖元。

透視除法:由於之前爲了方便模型視圖變換操作,我們用四維齊次座標作爲三維點座標的代表進行矩陣操作,所以需要通過一定的操作將齊次座標(x, y, z, q)轉換回三維點座標(x, y, z)。具體操作爲:齊次座標除以第四個分量q,然後丟棄第四個分量,轉換回歸一化的三維座標(x/q, y/q, z/q)。

 

    2-5)視口變換(view port)

           此時我們已經得到了歸一化座標,即所有的點座標都處於CCV中,所以需要通過縮放和位移使其在窗口(屏幕)輸出渲染。

           在OpenGL中提供了:

             - void glViewport( Glint x, GLin y, GLsizei width, GLsizei height )

               【x, y】視窗屏幕的左下角座標

               【width/height】視窗屏幕的實際寬高

    PS:此處需要提醒一下視口變換與投影變換的區別:

圖5 視口變換與投影變換的區別【7】

     2-6)最後得到窗口座標,進行光柵化處理。

 

 【名詞解釋 & 參考文獻】   

【1】光柵化(Rasterize)【像素化或柵格化】的渲染方式:

圖元(primitive)指點、線、三角形等基本幾何圖形,片元(fragment):在光柵化之後,裁剪後稱之爲片元,片元採用的是屏幕窗口座標

【2】幀緩衝區:幀緩存OR顯存,是屏幕顯示畫面的直接映像,邏輯上是一組由屏幕上所有像素組成的二維數組,每一個存儲單元負責對應屏幕上的一個像素,整個幀緩衝區對應的一幀圖像即爲當前屏幕顯示的畫面。一個完整的幀緩衝應當包括顏色緩存、深度緩存、模版緩存、積累緩存以及多重採樣緩存

【3】Shreiner Dave. Opengl Programming Guide: The Official Guide To Learning Opengl, Version 2.1, 6/E. Pearson Education India, 2008.

【4】仿射變換:在幾何中,一個向量空間進行一次線性變換外加一次平移操作,變換成爲另一個向量空間,可以認爲線性變換 (向量y=A·向量x )是一次特殊的仿射變換 (向量y=A·向量x+ 向量B )  

【5】【OPENGL】第三篇 着色器基礎(一):https://www.cnblogs.com/MyGameAndYOU/p/4691081.html

6】songho:OpenGL Projection Matrix( http://www.songho.ca/opengl/gl_projectionmatrix.html

  【7】圖片來自於 :http://www.cnblogs.com/liangliangh/p/4089582.html

  【8】本文的一部分內容是來源這位大神的博客:http://www.twinklingstar.cn/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章