拓幻圖形學工程師教學手冊(第三講)|一字一字敲出OpenGL學習教程

上一講已經介紹了的OpenGL紋理部分的內容,今天這講關於OpenGL光照(Lighting)示例代碼也都在公司github共有倉了,不知道各位是不是試著跑過,沒跑過也不要緊,繼續往下聽吧,最後總要實踐的,講再多不如自己上手一試。我記得Dr. Lee當初還做了蠻多不錯的示例代碼,比如旋轉的五彩菊花,回頭我讓他貢獻一下他的五彩菊花,放到我們的Github上給大家參考。後期Dr. Lee也將推出一些他自己的教程,這可是來自美國克萊姆森大學的教程,大家不要錯過,關注我們微信公眾號,一起來學習吧。

5. 光照(Lighting)

5.1 基本概念

跑過「太陽系」工程的同學一定發現,除了上一講的紋理映射實現將太陽及其行星表面紋理進行實現外,還有一個重點就是光。太陽系中唯一的光源就是太陽,其他行星只是進行光反射等,並且太陽光光源是向四面八方照射的,這個系統我們可以用OpenGL光照來進行模擬。

先來看兩張不同的圖,一張有光照一張沒有,看看區別就知道光照在渲染方面其實還是很重要的。

接下來就是具體的光照內容了。

5.2 表面向量(Surface Normal)

先引入一個概念叫表面法線(Surface Normal),也就是表面上某一點的法向量(Normal Vector),是在該點處與表面垂直的方向。對於平面,其上各點的法向是一樣的,統一為這個平面的法向。

以上是計算表面法線向量的方法,不多說。

這是對於平面而言,那麼更多時候繪製的不是平面而是曲面,該怎麼計算表面法線。

頂點法線(Vertex Normal)是過頂點的一個矢量,在生成曲面時,通常令頂點法線和相鄰平面的法線保持等角,這樣進行渲染時,會在平面接縫處產生一種平滑過渡的效果。

這樣就產生兩種計算表面法線的方法:Per-face和Per-vertex:

在OpenGL中使用方法如下:

Per-face:

Per-vertex:

所產生的效果,per-face會對於曲面會產生粗糙分割面的感覺,我們稱之為「Flat Shading」,per-vertex則會產生平滑感,稱之為「Smooth Shading」。

再介紹一個函數glShadeModel函數。用於控制opengl中繪製指定兩點間其他點顏色的過渡模式。參數一般為GL_SMOOTH(默認),GL_FLAT。OpenGL默認是將制定的兩點顏色進行插值,繪製之間的其他點,如果兩點的顏色相同,使用兩個參數效果相同,如果兩點顏色不同,GL_SMOOTH會出現過渡效果,GL_FLAT 則只是以指定的某一點的單一色繪製其他所有點。看下效果:

GL_FLAT:

GL_SMOOTH:

來看看具體調用和結合Per-face/Per-vertex的效果:

注意這裡介紹一下,glEnable( GL_NORMALIZE ),在進行光照計算之前自動單位化法向量。之所以需要自動單位化法向量是因為法向量會受到glScalef的影響,當glScalef將物體的坐標放大k倍時,法向量變為1/k。具體調用如下:

5.3 OpenGL內置光照模型

OpenGL光照分為三種,Ambient(環境光),Diffuse(漫射光)和Specular(鏡面反射光)。

Ambient 不依賴於光源的方向。光線在物體表面上向各個方向上均勻泛射,場景中的物體都會泛射光,這些泛射光又會照射到其他 物體上繼續被泛射,直到光子能量耗盡為止,這樣整個場景中散布著這樣的泛射光。可通過設置一個顏色常量來表示環境光。Ambient = a constant。

Diffuse 只依賴於光源的方向和法線的方向。因此為只和表面與光線入射夾角有關的光線。我們之所以能看到物體,就是因為物體將入射的光然後向各個方向反射(所以稱之為漫反射)。物體的漫反射材質屬性對物體的顏色起著決定性作用。Diffuse = I*cosΘ,Θ為入射角角度,也就是光來的方向和法線的夾角。

Specular依賴於光源的方向,法線的方向和視角的方向。不但和表面與光線入射夾角有關,而且還和觀察角度有關的光線,並且根據表面光滑程度,呈現不同亮度,越光滑,越容易產生高光區域。在 OpenGL 中,鏡面光的強度可通過光滑度(shininess)來調節。

Specular = I*cossφ ,其中指數s就是光滑度。1/s就是粗糙度(Roughness)。

看一下效果圖:

下面介紹一下三種不同的光源。

Directional Light 平行光(方向光),可以改變角度。可以聯想太陽光。

Point Light 點光源(由一個點向四周發射光源),可以改變位置。可以聯想燈泡。

Spot Light 聚光燈(聚光/錐光)。比較耗費資源,可以改變位置和角度。可以聯想手電筒。

再看一下光源位置不同造成的不同效果:

左邊是點光源在人眼位置,右邊為點光源在坐標原點。

5.4 使用OpenGL光照

教大家一個簡單的運用光照的代碼:

然後再設置全局光照信息:

這樣有個好處就是可以輕鬆控制光的強度,比如這裡的0.3f。

設置材質:

設置光源特性:

可以將這些代碼整合為以下代碼,放到方法體裡面去:

具體怎麼使用,還需要各位參見Github我們的源碼再實戰一下。才能真正體會到光照這一塊的用法。

這是新年前最後一更啦,要放假啦!大家也假期多休息多陪陪家人吧,別碼代碼了,哈哈哈。年後再見吧??。

推薦閱讀:

圖形渲染中關於CPU和GPU的一些問題?
計算機圖形學中,面的最小基本單位為什麼一般是三角形?
對多重採樣(MSAA)原理的一些疑問?
VAO和EBO解綁定的坑?
OpenGL ES 和 Unity3D 是什麼關係?

TAG:OpenGL | 計算機圖形學 |