从零开始学习OpenGL ES之五 – 材质
生活随笔
收集整理的這篇文章主要介紹了
从零开始学习OpenGL ES之五 – 材质
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
從零開始學習OpenGL ES之五 – 材質
|
顏色是什么
這可能是對小學美術課的復習。為什么現實世界會有顏色?是什么造成的? 我們看得見的光被稱為 光的可見頻譜 。根據不同的波長我們可以感知到不同的顏色。在可見光譜的一端是低波長高頻率的紫色和藍色,而在另一端是低頻高波長的橘色和紅色: 電磁波在這個范圍之外,因此不是“可見光”,盡管這只是人工的區分方法,它們的唯一不同在頻率和波長,在于人眼的感知。盡管有各種方法感知各種電磁波的能力,但從OpenGL的角度出發,我們只關心可見光譜。 “白色光”包括等量的所有波長。換言之,白光之所以是白色的是因為它包括了所有(或至少大部分)可見光的頻率。如果你曾經做過棱鏡試驗,那么你可能看過如下效果: 棱鏡反射白光,各種波長被分離出來。這就是彩虹產生的原理。 如果你看到一個物體呈藍色,那么實際上是該物體吸收了大部分可見光譜低頻部分。它吸收了紅,橘,黃和綠光。根據藍色的不同色度,它還可能吸收一些紫色和藍色。 但大部分藍色的波長都被反射到你的眼睛。因為一些可見光被吸收了,由于它不再包括可見光譜中的所有波長所以反射到你眼中的光不再是白色。 簡單吧?讓我們看看這些是怎樣運用在OpenGL的。OpenGL 材質
我們通過定義材質的反射光來定義OpenGL ES中的材質,正如現實世界中一樣。如果一個材質定義為反射紅光,那么在正常的白光下,它將顯示紅色。 在OpenGL中 (至少在使用光滑著色處理和光效時),材質是沒有顏色的。OpenGL具有分別定義材質是怎樣反射OpenGL光效三要素(環境,散射和高光)的能力。另外,它還具有指定材質 自發光(emissive) 屬性的能力,關于這點我們稍后再討論。指定材質
要在OpenGL創建一個材質,我們需要一次或多次調用 glMaterialf() 或者 glMaterialfv()。類似于上一篇文章中光效的定義,由于各屬性或元素需要分別通過這些調用了指定,所以我們通常必須多次調用這些函數以完全定義材質。所有未定義的元素或屬性默認值為0,或者以顏色來說為黑色。 傳遞給 glMaterialf() 或者 glMaterialfv() 的第一個參數總是用于指定是否材質影響多邊形的前,后或兩者的GL_ENUM。實際上除了為了與OpenGL兼容,第一個參數在OpenGL ES中沒有什么意義,因為只有一個有效的選項: GL_FRONT_AND_BACK,它簡單地表示材質適用于任何繪制的多邊形。如果你還記得第一部分,那么你應該知道三角形的正面和背面是由winding(頂點的繪制次序)決定的。默認情況下,只有三角形的正面被繪制出來,但是有可能讓OpenGL也繪制背面,或甚至只繪制背面,常規 OpenGL 允許你通過傳遞GL_FRONT,GL_BACK, 或者 GL_FRONT_AND_BACK來為正面和背面指定不同的材質。但是OpenGL ES僅支持GL_FRONT_AND_BACK。 glMaterialf() 或 glMaterialfv()的第二個參數是指示正在設定材質的哪個元素或屬性的 GL_ENUM。它們像傳遞給glLightfv()的值一樣,比如GL_AMBIENT ,另外還有些新的值我們稍后再談。 最終值是 GL_FLOAT或包括了實際屬性或元素的GL_FLOAT數組的指針。 材質的最重要元素是環境光和散射光,因為它們決定了材質是怎樣反射大量光線的。我們今天使用的項目代碼定義了正如太陽光或白熾燈產生的白色,它具有 平均分布的各種波長和顏色的光。如果光不是白色,球體看上去會有不同的外觀。例如,反射至紅色材質的藍光將產生紫色陰影。簡單起見,我們只使用白色光。當 然,你可以隨意改變光的顏色進行試驗看看光和材質是怎樣交互作用的。大部分時候,它們在OpenGL ES中的表示與現實生活中完全一樣。 下面是項目在添加材質前運行時的樣子: 如你所見,它具有一些環境光和更為顯著的散射光。環境光和散射光
當討論OpenGL的材質時,我們需要同時討論環境光和散射光,這是因為這兩個元素是一起工作從而決定物體被感知的顏色的。記住,散射光處于本文第 一個圖片中球體的頂部(亮×××),環境光則是下方的暗×××。材質怎樣反射這兩個元素決定了物體被感知的顏色。上圖的效果可以通過不止一種方法獲得。同樣 地,×××球以同樣比例反射環境光和散射光,但是場景中具有較少的環境光。 大約 90% 或更多的情況下,將材質的環境光和散射光參數設定成一樣。這樣做,使它們成為決定物體陰影和外觀的因素。實際上,有一種方法通過一個調用glMaterialfv()同時設定材質環境光和散射光。下面是定義材質為藍色的示例: GLfloat ambientAndDiffuse[] = {0.0, 0.1, 0.9, 1.0};glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ambientAndDiffuse); 正如 glColor4f(), 設置材質指示隨后所有物體繪制的方式直到另一個材質被指定。如果將上敘代碼放置于我們的繪制代碼之前,那么運行時你將看到球體變為藍色。由于環境光沒有散射光強,其下方只是稍暗。 有時你希望更多地控制并希望分別設定材質對環境光和散射光的反射方式。例如,下例中,材質從環境光反射藍色,從散射光反射紅色: GLfloat ambient[] = {0.0, 0.1, 0.9, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);GLfloat diffuse[] = {0.9, 0.0, 0.1, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); 運行結果: 在此情況下,它看上去像我們投射了有色光到球體上,實際上卻不是這樣。原因是我們反射了與環境光不一樣的定向光線。 大部分情況下,如果你希望產生彩色光的效果,你只需創建彩色光線然后使用GL_AMBIENT_AND_DIFFUSE來指定材質顏色。但是有時卻希望分別設置它們產生特殊效果或在不引起創建額外光線開銷的情況下假造一個分離的彩色點光源。記住:你每增加一個光源,也就增加了每秒鐘的運算量,所以有時候欺騙并不完全是一件壞事。
高光和光澤
你還可以單獨設置場景中高光元素的反射方式,從而控制高光“熱點”的亮度。一個叫 GL_SHININESS的參數與材質的高光元素一起定義了高光熱點的大小。如果你設定了材質的 GL_SPECULAR 值,你還應該定義其反光度。反光度越高,高光反射越小,所以默認值 0.0 幾乎完全淹沒了散射光,因此看上去很糟糕。 讓我們回到藍色球體,增加高光熱點: GLfloat ambientAndDiffuse[] = {0.0, 0.1, 0.9, 1.0};glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ambientAndDiffuse);GLfloat specular[] = {0.3, 0.3, 0.3, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 25.0); 我們使用了一個較暗的白色作為球體的高光值。這個值看上去有些小,但就是這么小的值也能產生顯著的效果。光線高光元素的值與材質的高光元素相乘所產生的光集中在材質反光度指定的區域。下面是上敘代碼產生的結果: 現在,球體上有一個小的區域具有更強的反射光。我們可以通過增強光或光的高光元素,或者通過增加材質的反光度使這個點更亮。我們還可以通過調整反光度改變高光的大小。材質反光度越高,高光越集中。例如,如果我們將反光度從25.0 改為 50.0,我們將得到一個更小的熱點,它使得球體顯得更具有光澤。 但是,有一點要小心。本文之所以改為使用球體的部分原因以及為什么球體使用較高的頂點數目的原因是高光在一個低面數的物體上看上去實在糟糕。注意一下,如果我減少球體的頂點數會發生什么: 低面片 高光使三角形邊緣突出,高光通常在我們的游戲中經常使用的低面片的物體上表現不佳。在常規OpenGL中,有一個稱為 著色器(shader) 的機制可以用來為低面片物體產生較為理想的結果,但目前iPhone上的OpenGL ES并不支持此功能(譯者注:iPhone 3GS支持OpenGL ES 2.0,有shader功能。但有一個問題就是OpenGL ES 1.1與OpenGL ES 2.0并不完全兼容)在游戲中如果你想使低面片物體漂亮的唯一方法就是完全摒棄高光元素而使用紋理映射,這將在下一篇文章中談到。
自發光
還剩最后一個材質的重要屬性,它稱為自發光元素。通過設定自發光元素,使得材質看上去會發射我們指定的顏色。它并不是真正在發光。例如,其周邊物體 并不會被發射的光線影響。如果你希望一個物體像燈泡一樣發光照亮其他物體,由于在OpenGL ES中只有光源會發光(聽上去像廢話),你需要將自發光元素和與物體同一位置處的實際光源結合起來。但是自發光元素可以使物體漂亮地發光。 例如,我們可以為藍色球體添加綠色的光澤: GLfloat emission[] = {0.0, 0.4, 0.0, 1.0};glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission); 結果如下: 自發光元素影響整個材質,因此 GL_EMISSION的值將與落入物體指定區域的任何類型的光相疊加。請注意,甚至上圖中的高光部分也成了一點藍-綠色而不是純白色。在高光點處其效果是很微小的,但在只有環境光被反射的底部效果更為明顯。它實際影響整個物體。
原文見:OpenGL ES From the Ground Up, Part 5: Living in a Material World
轉載于:https://blog.51cto.com/mkhgg/656329
總結
以上是生活随笔為你收集整理的从零开始学习OpenGL ES之五 – 材质的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一起谈.NET技术,页面片段缓存(二)
- 下一篇: Silverlight for Wind