[OpenGL] 一些功能的實作練習 - Some Practice of OpenGL

完成了一段 OpenGL 的線上課程後,基本上理解了幾個 OpenGL 功能的實作方式,並且試過了從讀取 Model 到渲染至螢幕上的流程。

不過課程中的解說僅止於 “如何做到”,為了能確認 “為何這麼做”,釐清每個 OpenGL API 如何呼叫,我開始了一個練習的新專案。

用這篇文章紀錄一下目前所做出來的練習與心得。

目前實做出來的幾個項目:

  • Shader 讀取
  • Material 的封裝及覆用
  • 幾個基本形狀 Mesh 的實時建立、組合
  • 平行光的模型
  • Rendered Texture
  • Shadow Map。

到第三點為止,只是將所知道的步驟整理成幾個 class,方便呼叫、建立與渲染,同時統一幾個傳遞資料到 Shader Program 時的欄位名稱,達成可以隨時重新組合覆用的 Mesh - Material 關聯。

另外寫一系列方法來 runtime 建立幾種基本形狀的 Mesh,這邊的數學花了不少時間。最後把幾個 Mesh 排列成測試場景,並且組合成單一 Mesh,這樣只要進行一次渲染便可。

mesh 1
mesh 2

完成了基本的測試場景,我下一步想加上的是 Lighting。

一般來說場景中不會只有一個光源,或者一種光源,如何有效的傳遞不同數量與種類的光源資料到不同的 Shader 中,成了必須解決的問題。為此需要一個管理光源的結構,因為對其他功能的實作還不完全確立,覺得馬上開始規劃核心結構有點過早,因此這邊我只用一個平行光當作測試。

lighting 1
lighting 2

Rendered Texture 是在線上課程中沒有遇過的功能,同時也是實作陰影所必要的前置動作,這邊要從網路上尋找資料來開始。

我發現 Rendered Texture 是個很好的練習題材,可以從建立 Frame Buffer 開始了解許多 API,原本這部分是由 GLFW 這個跨平台視窗 Library 代勞所以不必實作的。

這邊只透過網路上的片面說明,一開始是得到有點錯誤的結果,最後追查後發現如果 Texture 的大小跟視窗不同,需要切換 Viewport 的設定,才能有適當的渲染範圍。

render texture 1
render texture 1
render texture 1

Shadow Map 的陰影部分,一樣也是從網路上找了幾份資料來參考後才開始實作。跟光源一樣,每種不同的光源陰影的實作都有些許差異,組合數個光源也會讓情況變得更複雜,還好我目前只有一個平行光! 大致的過程,是要先用 RenderTexture 取得光源角度的深度紀錄,然後將這份紀錄傳到物體的 Shader 中,在渲染時判斷 fragmant 是否在陰影中。

目前我只有做到基本的陰影,精細度跟柔邊等細節都沒有做處理,所以在目前的場景看起來效果還行,但換個場景可能就會爆炸了 …

shadow 1
shadow 1

到目前為止實作的功能可以大致完成一個基本的場景配置,但是專案的類別結構已經開始混亂了。

接下來預計會梳理一下這幾個功能,整理如何共用、管理資源,場景資料的歸納與傳遞等,讓專案乾淨一點後再繼續其他實作練習。