學習OpenGL-ES: 3 - 3D繪圖原理


1,成像模型

計算機圖形的生成,總是可以抽象成三個過程:輸入數據 -> 處理數據 -> 輸出人眼識別的圖像。

其中最后一個過程,在之前的文章:學習OpenGL-ES: 1 - 像素、顏色、顯存、初始化 中已經有過比較詳細的描述,最終輸出的是像素(顏色)點陣,由硬件激發顯示屏,發射出相應顏色的光線,被人眼接受,形成圖像視覺。所以OpenGL ES 的繪圖過程可描述為:輸入數據 -> 處理數據 -> 輸出像素點陣。  

那么,輸入數據和處理數據又是怎樣的呢?

很自然的可以想到通過模擬人眼的輸入和處理過程來進行計算機處理。對人眼而言,觀察物體實際上是物體在視網膜成像的過程,首先存在物體,然后存在光源,物體反射(自發射)光線,這些光線進入人眼,在視網膜成像,刺激視覺神經細胞,令人產生視覺。 

相應的,對於計算機,我們需要描述物體,描述光源,模擬光源和物體的作用過程(吸收、反射、折射光線),模擬視網膜成像;但人眼本身是一個非常復雜的器官,很難完全對其進行模擬,一個簡化方法是使用相機模型來代替人眼模型。和人眼模型相比,我們同樣需要描述物體,描述光源,模擬光源和物體的作用過程,但是只需要用比較簡單的相機成像來替代復雜的視網膜成像即可。

所以,OpenGL ES的繪圖過程可描述為:輸入物體數據、光源數據 -> 模擬光照,模擬投影(成像) -> 輸出像素點陣。 

2,輸入物體數據 

如何描述一個物體?讓我們看看一個物體有哪些屬性(對於視覺而言): 

  a, 位置:

    首先,我們需要知道物體的位置,如果物體在我們的視野以外,我們就無法看到它。 

  b,朝向:

    其次,我們需要知道物體的朝向,當物體側面對着我們時,我們看到的內容是不同於物體背面對着我們時的。 

  c,形狀:

    這點很明顯。 

  d,顏色:

     顏色其實是物體和光線相互作用的結果。

   e, 材質:

    金屬表面有光澤,而木頭表面比較粗糙,這也是物體和光線相互作用的結果,我們用材質來描述決定這種結果的屬性。

 接下來我們看看如何在計算機中去描述這些屬性,注意我們是在一個三維空間中:

  a, 位置: 

    人們日常生活中所用的位置總是一個相對值,比如:我在你前面100米。另一個例子是地圖,人們查看地圖時,總是先確定一個參考點,比如我當前位於XX,然后再確定另一個點:火車站在我右手邊2000米。同樣,在計算機中,我們也也使用相對位置,我們需要一個參考點,通常這個點是某個坐標系的原點,所有對位置的描述都是相對於這個原點進行的。 

    那么,我們需要在計算機中描述這些東西(注:以下描述為了簡單起見,可能不夠嚴謹): 

    坐標系 - 通常是笛卡爾坐標系,通過描述原點(位置)和三個正交基(坐標軸xyz,向量)的數學表示來進行。 

    物體位置 - 物體(中心點)在給定坐標系中的坐標。 

  b, 朝向: 

    同位置一樣,這也是個相對值。通常我們先給定一個正方向,然后描述相對於這個正方向的旋轉來描述物體的朝向,比如:先讓物體處於正方向,然后圍繞X軸旋轉30度,再圍繞Y軸旋轉50度,就是現在的朝向。

      那么,我們需要在計算機中描述這些東西: 

    正方向:事實上,我們不需要描述這個東西,我們假定這個東西為1,那么 朝向 = 1 * 旋轉,因此我們只需要描述旋轉就可以了。

     旋轉:有多種描述方式,矩陣、歐拉角、四元數等,后續再進行詳細的講解。

   c,形狀:

     三維空間中的物體,可以看做由無數個緊密點組成,也可以看做由無數個緊密曲面組成,這兩種表述都需要極大的計算量(有例外),不適合計算機。

     計算機圖形學中最常見的方法是使用大量細小的平面去模擬曲面,這個概念比較難以描述,任何看過3D建模工具中模型的線框圖的人應該都能很容易理解,如果你不理解,建議去看一看,這里不再贅述。

     平面有很多種,出於效率(算法限制)以及硬件實現復雜度的考量,我們一般要求平面為凸多邊形,更進一步,OpenGL ES 只支持三角形。所以,我們使用大量的三角形來描述物體形狀;那么,如何描述三角形本身呢,一個直觀的想法是描述所有頂點,以及頂點組成三角形的方式,OpenGL ES 確實是采用這樣的方式,后續再進行詳細的說明。

   d, 顏色:

     當物體受到光照時,對於RGB中的每一種,它都會進行吸收、反射,所以顏色的定義來源於吸收了RGB中的多少,反射了多少。比如假設0代表完全吸收,1代表完全反射,那么(r,g,b) = (1,0,0)表示完全反射紅光,吸收藍光和綠光,那么我們所看到的就是紅色的物體(假設使用白光照射)。

  e,材質:

     如果物體表面光滑,則大部分入射光會以相同的角度反射出去,我們稱之為鏡面反射;反之如果物體表面粗糙,大部分入射光會進行近似無序的散射;真實的物理過程比較復雜,一般我們會采用簡化的模型,我們需要描述有多少比例的光進行鏡面反射,多少比例的光進行散射。

 3,輸入光源數據

 a, 位置:

  光源可視為物體,位置的描述方式和物體一樣。

 b, 顏色:

  發射的光線中RGB分量的強度。

 c, 強度:

  光源的亮度。

 d, 方向:

  是球形發射的點光源,還是集中在一個方向的聚光燈,還是無窮遠處點光源發射過來的(近似)平行光。

 e, 衰減度:

   隨距離增大的衰減程度。

  4,模擬光照

  總體來說分為兩大類,局部光照和全局光照:

 局部光照:

   對指定物體,局部光照只考慮光源和這個物體的作用,不考慮其它物體。主要為 Phone光照模型。

 全局光照:

   對指定物體,全局光照不僅僅考慮光源和這個物體的作用,還考慮場景中的其它物體影響,比如光源照在A物體上,A物體反射的光照射在B物體上,則B物體同時受到光源的光和A反射光的影響。

  全局光照主要使用光線跟蹤(Ray Tracing)和輻射度(Radiosity)兩種方法,前者顧名思義,追蹤所有進入人眼的光線(光源直射、反射、反射的反射、反射的反射的反射。。。);后者基於一個場景內光線總能量守恆的原理,進行相應計算。

 全局光照有更好的效果,更復雜的實現,更多的計算量。光照是個復雜的話題,這里只做簡單描述。

 5,模擬投影

物體擺好,光源設置好之后,從不同的位置不同的角度觀察,所看到的圖像是不同的,觀察的過程本質上是投影的過程,將三維空間中的點投影到一個2D平面,形成圖像。對人眼而言,投影到視網膜,對相機而言,投影到底片。為了模擬投影過程,我們需要設置觀察者,以相機為例:

  1,將相機放置在某個位置,這和放置物體是完全一樣的。

  2,調整好相機的朝向,這和調整物體朝向是完全一樣的。

  3,設定相機的觀察范圍,所有在這個觀察范圍內的物體都是可見的,在此之外的物體都是不可見的。觀察范圍通常是一個多面體,位於多面體內的物體可見,體外的物體不可見,稱之為視見體。對照相機來說,這一步對應着調整焦距(視角)。

  4,設定投影平面,這一步和第三步是密切相關的,容易想象,只有投影平面之前的物體才能投影到該平面,而位於投影平面之后的物體都是不可見的。

  5,拍攝(投影)。

  6,沖洗照片,我們可以以任意的尺寸沖洗照片。

6,輸出像素點陣

將前面計算得出的像素(顏色)數據寫入顯存,通知硬件刷新(顯示畫面)。

7,總結:

OpenGL ES 的粗略繪制過程如下:

用大量三角形構造3D物體,指定物體位置、朝向,設置物體顏色、材質,設定光源,計算光照結果,投影,刷新顯示。

以上是我們所推導的繪制過程,OpenGL ES的實際繪制過程包含比這些要多的內容,比如裁剪、紋理等,但其本質不變。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM