光照-03.材質(zhì)

在真實(shí)世界里,每個(gè)物體會(huì)對(duì)光產(chǎn)生不同的反應(yīng)。鋼看起來(lái)比陶瓷花瓶更閃閃發(fā)光喳资,一個(gè)木頭箱子不會(huì)像鋼箱子一樣對(duì)光產(chǎn)生很強(qiáng)的反射。每個(gè)物體對(duì)鏡面高光也有不同的反應(yīng)腾供。有些物體不會(huì)散射(Scatter)很多光卻會(huì)反射(Reflect)很多光仆邓,結(jié)果看起來(lái)就有一個(gè)較小的高光點(diǎn)(Highlight),有些物體散射了很多伴鳖,它們就會(huì)產(chǎn)生一個(gè)半徑更大的高光节值。如果我們想要在OpenGL中模擬多種類型的物體,我們必須為每個(gè)物體分別定義材質(zhì)(Material)屬性榜聂。

在前面的教程中搞疗,我們指定一個(gè)物體和一個(gè)光的顏色來(lái)定義物體的圖像輸出,并使之結(jié)合環(huán)境(Ambient)和鏡面強(qiáng)度(Specular Intensity)元素须肆。當(dāng)描述物體的時(shí)候匿乃,我們可以使用3種光照元素:環(huán)境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)豌汇、鏡面光照(Specular Lighting)定義一個(gè)材質(zhì)顏色幢炸。通過(guò)為每個(gè)元素指定一個(gè)顏色,我們已經(jīng)對(duì)物體的顏色輸出有了精密的控制【芗現(xiàn)在把一個(gè)鏡面高光元素添加到這三個(gè)顏色里宛徊,這是我們需要的所有材質(zhì)屬性:

#version 330 core
struct Material
{
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};
uniform Material material;

在片段著色器中,我們創(chuàng)建一個(gè)結(jié)構(gòu)體(Struct)逻澳,來(lái)儲(chǔ)存物體的材質(zhì)屬性闸天。我們也可以把它們儲(chǔ)存為獨(dú)立的uniform值,但是作為一個(gè)結(jié)構(gòu)體來(lái)儲(chǔ)存可以更有條理斜做。我們首先定義結(jié)構(gòu)體的布局苞氮,然后簡(jiǎn)單聲明一個(gè)uniform變量,以新創(chuàng)建的結(jié)構(gòu)體作為它的類型陨享。

就像你所看到的葱淳,我們?yōu)槊總€(gè)馮氏光照模型的元素都定義一個(gè)顏色向量。ambient材質(zhì)向量定義了在環(huán)境光照下這個(gè)物體反射的是什么顏色抛姑;通常這是和物體顏色相同的顏色赞厕。diffuse材質(zhì)向量定義了在漫反射光照下物體的顏色。漫反射顏色被設(shè)置為(和環(huán)境光照一樣)我們需要的物體顏色定硝。specular材質(zhì)向量設(shè)置的是物體受到的鏡面光照的影響的顏色(或者可能是反射一個(gè)物體特定的鏡面高光顏色)皿桑。最后,shininess影響鏡面高光的散射/半徑蔬啡。

這四個(gè)元素定義了一個(gè)物體的材質(zhì)诲侮,通過(guò)它們我們能夠模擬很多真實(shí)世界的材質(zhì)。這里有一個(gè)列表devernay.free.fr展示了幾種材質(zhì)屬性箱蟆,這些材質(zhì)屬性模擬外部世界的真實(shí)材質(zhì)沟绪。下面的圖片展示了幾種真實(shí)世界材質(zhì)對(duì)我們的立方體的影響:

如你所見,正確地指定一個(gè)物體的材質(zhì)屬性空猜,似乎就是改變我們物體的相關(guān)屬性的比例绽慈。效果顯然很引人注目,但是對(duì)于大多數(shù)真實(shí)效果辈毯,我們最終需要更加復(fù)雜的形狀坝疼,而不單單是一個(gè)立方體。在下面的教程中谆沃,我們會(huì)討論更復(fù)雜的形狀钝凶。

讓我們?cè)囋囋谥髦袑?shí)現(xiàn)這樣的一個(gè)材質(zhì)系統(tǒng)。

設(shè)置材質(zhì)

我們?cè)谄沃髦袆?chuàng)建了一個(gè)uniform材質(zhì)結(jié)構(gòu)體唁影,所以下面我們希望改變光照計(jì)算來(lái)順應(yīng)新的材質(zhì)屬性耕陷。由于所有材質(zhì)元素都儲(chǔ)存在結(jié)構(gòu)體中,我們可以從uniform變量material取得它們:

void main()
{
    // Ambient
    vec3 ambient = lightColor * material.ambient;

    // Diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse =lightColor * (diff * material.diffuse);

    // Specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
    vec3 specular = lightColor * (spec * material.specular);

    vec3 result = ambient + diffuse + specular;
    color = vec4(result, 1.0f);
}

你可以看到据沈,我們現(xiàn)在獲得所有材質(zhì)結(jié)構(gòu)體的屬性啃炸,無(wú)論在哪兒我們都需要它們,這次通過(guò)材質(zhì)顏色的幫助卓舵,計(jì)算結(jié)果輸出的顏色南用。物體的每個(gè)材質(zhì)屬性都乘以它們對(duì)應(yīng)的光照元素。

通過(guò)設(shè)置適當(dāng)?shù)膗niform掏湾,我們可以在應(yīng)用中設(shè)置物體的材質(zhì)裹虫。當(dāng)設(shè)置uniform時(shí),GLSL中的一個(gè)結(jié)構(gòu)體并不會(huì)被認(rèn)為有什么特別之處融击。一個(gè)結(jié)構(gòu)體值扮演uniform變量的封裝體筑公,所以如果我們希望填充這個(gè)結(jié)構(gòu)體,我們就仍然必須設(shè)置結(jié)構(gòu)體中的各個(gè)元素的uniform值尊浪,但是這次帶有結(jié)構(gòu)體名字作為前綴

// 設(shè)置uniform Material material(GLSL結(jié)構(gòu)體)
GLint matAmbientLoc = glGetUniformLocation (lightingShader.Program, "material.ambient");
GLint matDiffuseLoc = glGetUniformLocation (lightingShader.Program, "material.diffuse");
GLint matSpecularLoc = glGetUniformLocation (lightingShader.Program, "material.specular");
GLint matShininessLoc = glGetUniformLocation (lightingShader.Program, "material.shininess");

glUniform3f (matAmbientLoc, 1.0f, 0.5f, 0.31f);
glUniform3f (matDiffuseLoc, 1.0f, 0.5f, 0.31f);
glUniform3f (matSpecularLoc, 0.5f, 0.5f, 0.5f);
glUniform1f (matShininessLoc, 32.0f);

我們將ambient和diffuse元素設(shè)置成我們想要讓物體所呈現(xiàn)的顏色匣屡,設(shè)置物體的specular元素為中等亮度顏色封救;我們不希望specular元素對(duì)這個(gè)指定物體產(chǎn)生過(guò)于強(qiáng)烈的影響。我們同樣設(shè)置shininess為32捣作。我們現(xiàn)在可以簡(jiǎn)單的在應(yīng)用中影響物體的材質(zhì)誉结。

運(yùn)行程序,會(huì)得到下面這樣的結(jié)果:

看起來(lái)很奇怪不是嗎券躁?

光的屬性

這個(gè)物體太亮了惩坑。物體過(guò)亮的原因是環(huán)境、漫反射和鏡面三個(gè)顏色任何一個(gè)光源都會(huì)去全力反射也拜。我們想做一個(gè)相同的系統(tǒng)以舒,但是這次為每個(gè)光照元素指定強(qiáng)度向量。如果我們想象lightColor是vec3(1.0)慢哈,代碼看起來(lái)像是這樣:

vec3 ambient = vec3(1.0f) * material.ambient;
vec3 diffuse = vec3(1.0f) * (diff * material.diffuse);
vec3 specular = vec3(1.0f) * (spec * material.specular);

所以物體的每個(gè)材質(zhì)屬性返回了每個(gè)光照元素的全強(qiáng)度蔓钟。這些vec3(1.0)值可以各自獨(dú)立的影響各個(gè)光源,這通常就是我們想要的卵贱。我們要設(shè)置光的ambient亮度為一個(gè)小一點(diǎn)的值奋刽,從而限制環(huán)境色:
`

vec3 result = vec3(0.1f) * material.ambient;

我們可以用同樣的方式影響光源diffuse和specular的強(qiáng)度。這和我們前面教程所做的極為相似艰赞;你可以說(shuō)我們已經(jīng)創(chuàng)建了一些光的屬性來(lái)各自獨(dú)立地影響每個(gè)光照元素佣谐。我們希望為光的屬性創(chuàng)建一些與材質(zhì)結(jié)構(gòu)體相似的東西

struct Light
{
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
uniform Light light;

一個(gè)光源的ambient、diffuse和specular光都有不同的亮度方妖。環(huán)境光通常設(shè)置為一個(gè)比較低的亮度狭魂,因?yàn)槲覀儾幌Mh(huán)境色太過(guò)顯眼。光源的diffuse元素通常設(shè)置為我們希望光所具有的顏色党觅;經(jīng)常是一個(gè)明亮的白色雌澄。specular元素通常被設(shè)置為vec3(1.0f)類型的全強(qiáng)度發(fā)光。要記住的是我們同樣把光的位置添加到結(jié)構(gòu)體中杯瞻。

在程序中設(shè)置light.position

GLint lightPosLoc = glGetUniformLocation (lightingShader.Program, "light.position");
glUniform3f (lightPosLoc, lightPos.x, lightPos.y, lightPos.z);

就像材質(zhì)uniform一樣镐牺,需要更新片段著色器:

vec3 ambient = light.ambient * material.ambient;
vec3 diffuse =light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);

然后我們要在應(yīng)用里設(shè)置光的亮度:

GLint lightAmbientLoc = glGetUniformLocation (lightingShader.Program, "light.ambient");
GLint lightDiffuseLoc = glGetUniformLocation (lightingShader.Program, "light.diffuse");
GLint lightSpecularLoc = glGetUniformLocation (lightingShader.Program, "light.specular");

glUniform3f (lightAmbientLoc, 0.2f, 0.2f, 0.2f);
glUniform3f (lightDiffuseLoc, 0.5f, 0.5f, 0.5f);        // 讓我們把這個(gè)光調(diào)暗一點(diǎn),這樣會(huì)看起來(lái)更自然
glUniform3f (lightSpecularLoc, 1.0f, 1.0f, 1.0f);

現(xiàn)在魁莉,我們調(diào)整了光是如何影響物體所有的材質(zhì)的睬涧,我們得到一個(gè)更像前面教程的視覺輸出。這次我們完全控制了物體光照和材質(zhì)

Image 065.png

現(xiàn)在改變物體的外觀相對(duì)簡(jiǎn)單了些旗唁。我們做點(diǎn)更有趣的事畦浓!

不同的光源顏色

目前為止,我們使用光源的顏色僅僅去改變物體各個(gè)元素的強(qiáng)度(通過(guò)選用從白到灰到黑范圍內(nèi)的顏色)检疫,并沒有影響物體的真實(shí)顏色(只是強(qiáng)度)讶请。由于現(xiàn)在能夠非常容易地訪問(wèn)光的屬性了,我們可以隨著時(shí)間改變它們的顏色來(lái)獲得一些有很意思的效果屎媳。由于所有東西都已經(jīng)在片段著色器做好了夺溢,改變光的顏色很簡(jiǎn)單论巍,我們可以立即創(chuàng)建出一些有趣的效果:
視頻演示

如你所見,不同光的顏色極大地影響了物體的顏色輸出风响。由于光的顏色直接影響物體反射的顏色(你可能想起在顏色教程中有討論過(guò))嘉汰,它對(duì)視覺輸出有顯著的影響。

利用sin和glfwGetTime改變光的環(huán)境和漫反射顏色钞诡,我們可以隨著時(shí)間流逝簡(jiǎn)單的改變光源顏色:

glm::vec3 lightColor; 
lightColor.x = sin (glfwGetTime () * 2.0f);
lightColor.y = sin (glfwGetTime () * 0.7f);
lightColor.z = sin (glfwGetTime () * 1.3f);

glm::vec3 diffuseColor = lightColor * glm::vec3 (0.5f);
glm::vec3 ambientColor = diffuseColor * glm::vec3 (0.2f);

glUniform3f (lightAmbientLoc, ambientColor.x, ambientColor.y, ambientColor.z);
glUniform3f (lightDiffuseLoc, diffuseColor.x, diffuseColor.y, diffuseColor.z);

嘗試和實(shí)驗(yàn)使用這些光照和材質(zhì)值,看看它們?cè)鯓佑绊憟D像輸出的湃崩。你可以從這里找到程序的源碼荧降。

練習(xí)

你能像我們教程一開始那樣根據(jù)一些材質(zhì)的屬性來(lái)模擬一個(gè)真實(shí)世界的物體嗎? 注意材質(zhì)表中的環(huán)境光顏色與漫反射光的顏色可能不一樣攒读,因?yàn)樗麄儾]有把光照強(qiáng)度考慮進(jìn)去來(lái)模擬朵诫,你需要將光照顏色的強(qiáng)度改為vec(1.0f)
來(lái)輸出正確的結(jié)果:參考解答,我做了一個(gè)青色(Cyan)的塑料箱子薄扁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剪返,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子邓梅,更是在濱河造成了極大的恐慌脱盲,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件日缨,死亡現(xiàn)場(chǎng)離奇詭異钱反,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)匣距,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門面哥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人毅待,你說(shuō)我怎么就攤上這事尚卫。” “怎么了尸红?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵吱涉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我外里,道長(zhǎng)邑飒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任级乐,我火速辦了婚禮疙咸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘风科。我一直安慰自己撒轮,他們只是感情好乞旦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著题山,像睡著了一般兰粉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顶瞳,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天玖姑,我揣著相機(jī)與錄音,去河邊找鬼慨菱。 笑死焰络,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的符喝。 我是一名探鬼主播闪彼,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼协饲!你這毒婦竟也來(lái)了畏腕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茉稠,失蹤者是張志新(化名)和其女友劉穎描馅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體而线,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡流昏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吞获。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片况凉。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖各拷,靈堂內(nèi)的尸體忽然破棺而出刁绒,到底是詐尸還是另有隱情,我是刑警寧澤烤黍,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布知市,位于F島的核電站,受9級(jí)特大地震影響速蕊,放射性物質(zhì)發(fā)生泄漏嫂丙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一规哲、第九天 我趴在偏房一處隱蔽的房頂上張望跟啤。 院中可真熱鬧,春花似錦、人聲如沸隅肥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腥放。三九已至泛啸,卻和暖如春嚼贡,著一層夾襖步出監(jiān)牢的瞬間戈泼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工族扰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留种柑,地道東北人岗仑。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像莹规,于是被迫代替她去往敵國(guó)和親赔蒲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泌神,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 前面的材質(zhì)系統(tǒng)對(duì)于除了最簡(jiǎn)單的模型以外都是不夠的良漱,所以我們需要擴(kuò)展前面的系統(tǒng),我們要介紹diffuse和specu...
    IceMJ閱讀 3,117評(píng)論 0 2
  • 現(xiàn)實(shí)世界的光照是極其復(fù)雜的欢际,而且會(huì)受到諸多因素的影響母市,這是以目前我們所擁有的處理能力無(wú)法模擬的。因此OpenGL的...
    IceMJ閱讀 1,951評(píng)論 1 6
  • 一损趋、四大光照類型1.環(huán)境光(Ambient Light) 一個(gè)物體即使沒有直接被光源照射患久,但是只要有光線通過(guò)其他物...
    CarlDonitz閱讀 1,471評(píng)論 0 0
  • 1.娶老婆不要以傳宗接代為目的桐玻。 很多男人們?nèi)⒗掀懦3J艿絺鹘y(tǒng)思想的影響篙挽,傳宗接代、延續(xù)香火思想禁錮镊靴。似乎這個(gè)理由...
    影爾玫閱讀 395評(píng)論 0 1
  • (一)雪后铣卡,夕陽(yáng)浮在煙囪旁枝椏披上瓊裝風(fēng)過(guò),璣珠紛揚(yáng)落了一地梅花香 沒有鞋印人們?cè)趪鸂t思念一位姑娘冬啊這是你的憧憬...
    靜鈴音閱讀 611評(píng)論 45 83