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