08 - OpenGL ES學(xué)習(xí)之材質(zhì)

在現(xiàn)實世界里席舍,每個物體會對光產(chǎn)生不同的反應(yīng)布轿。比如說鉆石看起來閃閃發(fā)光,塑料看起來就回暗一些。表面比較光滑的反射光的時候會產(chǎn)生亮點汰扭,表面比較粗糙一點的稠肘,反射光會形成一個光斑。

在上一篇文章中东且,我們指定了一個物體和光的顏色启具,以及結(jié)合環(huán)境光和鏡面強(qiáng)度分量,來定義物體的視覺輸出珊泳。當(dāng)描述一個物體的時候鲁冯,我們可以用這三個分量來定義一個材質(zhì)顏色(Material Color):環(huán)境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和鏡面光照(Specular Lighting)色查。通過為每個分量指定一個顏色薯演,我們就能夠?qū)ξ矬w的顏色輸出有著精細(xì)的控制了。現(xiàn)在秧了,我們再添加反光度(Shininess)這個分量到上述的三個顏色中跨扮,這就有我們需要的所有材質(zhì)屬性了:

我們創(chuàng)建一個結(jié)構(gòu)體來表示材質(zhì):

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shineness;
};

ambient 表示在環(huán)境光照下這個物體反射的顏色,通常這個是和物體相同的顏色验毡,diffuse定義了在漫反射光照下物體的顏色(和環(huán)境光照一樣)衡创,specular設(shè)置的是鏡面光照對物體的顏色影響,最后晶通,shineness影響鏡面高光的散射/半徑(這里可以舉個例子解釋:比如光照到比較粗糙的表面璃氢,可能散射的光圈半徑就大一些,照到類似玻璃狮辽,鋼鐵這類物體的表面一也,形成的光斑直徑就很小)。
這四個元素定義了一個物體的材質(zhì)喉脖,通過它們椰苟,我們能模擬出很多現(xiàn)實世界中的材質(zhì)。但是要想模擬出很真實的效果树叽,這些參數(shù)需要很多次實驗才能得到較為準(zhǔn)確的結(jié)果舆蝴。
讓我們接著上一篇的代碼,用材質(zhì)結(jié)構(gòu)體代替物體顏色來模擬物體的效果
頂點著色器如下:

#version 300 es
precision mediump float;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shineness;
};

uniform vec3 lightColor;
//光源位置
uniform vec3 lightPos;

//觀察點的位置
uniform vec3 viewPos;

//物體材質(zhì)
uniform Material material;

in vec3 Normal;
in vec3 fragPos;

out vec4 gColor;

void main() {
    //計算環(huán)境光照
    vec3 ambient =  lightColor * material.ambient;
    
    //計算漫反射
    vec3 norm = normalize(Normal);
    vec3 lightDirection = normalize(lightPos - fragPos);
    
    float diffu = dot(norm,lightDirection);
    vec3 diffuse = lightColor * (diffu * material.diffuse);
    
    //計算鏡面光照
    
    //觀察向量
    vec3 viewDirection = normalize(viewPos - fragPos);
    //反射向量
    vec3 reflectDirection = reflect(-lightDirection,norm);
    
    float spec = pow(max(dot(viewDirection,reflectDirection), 0.0) , material.shineness);
    
    vec3 specular =  lightColor * (spec * material.specular);

    //最終顏色(這里指定物體顏色為紅色)
    vec3 result = ambient + diffuse + specular;

    gColor = vec4(result,1.0);
}

這里我們假定lightColor為(1.0,1.0,1.0),也就是白光

得到的效果如圖:


IMG_6706.PNG

這里我們看到了效果题诵,大致是對的洁仗,但是會不會很奇怪,為什么這么亮仇轻,在上一篇文章中京痢,我們通過一個環(huán)境光照強(qiáng)度和鏡面光照強(qiáng)度來控制這兩個分量對最終顏色的影響篷店,而這里我們?nèi)サ袅诉@兩個強(qiáng)度祭椰,所以相當(dāng)于環(huán)境光照臭家,漫反射光照和鏡面光照對物體顏色的影響都是以1.0的強(qiáng)度處理的,所以這里特別亮方淤。

這一步的代碼對應(yīng)的是Cube_material-01文件夾

那么接下來我們改進(jìn)這一點钉赁,我們定義一個結(jié)構(gòu)體Light:

struct Light {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

我們通過改變Light的三個參數(shù) ambient ,diffuse, specular來改變每種光照的強(qiáng)度携茂,

修改后的頂點著色器:

precision mediump float;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shineness;
};

struct Light {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform vec3 lightColor;
//光源位置
uniform vec3 lightPos;

//觀察點的位置
uniform vec3 viewPos;

//物體材質(zhì)
uniform Material material;

//光照的屬性
uniform Light light;

in vec3 Normal;
in vec3 fragPos;

out vec4 gColor;

void main() {
    //計算環(huán)境光照
    vec3 ambient =  light.ambient * material.ambient;
    
    //計算漫反射
    vec3 norm = normalize(Normal);
    vec3 lightDirection = normalize(lightPos - fragPos);
    
    float diffu = dot(norm,lightDirection);
    vec3 diffuse = light.diffuse * (diffu * material.diffuse);
    
    //計算鏡面光照
    
    //觀察向量
    vec3 viewDirection = normalize(viewPos - fragPos);
    //反射向量
    vec3 reflectDirection = reflect(-lightDirection,norm);
    
    float spec = pow(max(dot(viewDirection,reflectDirection), 0.0) , material.shineness);
    
    vec3 specular =  light.specular * (spec * material.specular);

    //最終顏色(這里指定物體顏色為紅色)
    vec3 result = ambient + diffuse + specular;

    gColor = vec4(result,1.0);

}

注意這幾處的修改:


修改

這里我們設(shè)置的光的顏色還是白色光 vec3(1.0,1.0,1.0);

這里我們傳入Light結(jié)構(gòu)體你踩,對這幾種光照強(qiáng)度進(jìn)行設(shè)置:


glUniform3f(glGetUniformLocation(_esContext.program, "material.ambient"), 1.0, 0.5, 0.31);
    glUniform3f(glGetUniformLocation(_esContext.program, "material.diffuse"), 1.0, 0.5, 0.31);
    glUniform3f(glGetUniformLocation(_esContext.program, "material.specular"), 0.5, 0.5, 0.5);
    glUniform1f(glGetUniformLocation(_esContext.program, "material.shineness"), 32.f);
    
    glUniform3f(glGetUniformLocation(_esContext.program, "light.ambient"), 0.2 ,0.2, 0.2);
    glUniform3f(glGetUniformLocation(_esContext.program, "light.diffuse"), 0.5, 0.5, 0.5);
    glUniform3f(glGetUniformLocation(_esContext.program, "light.specular"), 1.0, 1.0, 1.0);

效果如圖:


最終效果

這樣看上去是不是比較接近真實效果了。
這一步對的代碼對應(yīng)Cube_material-02這個文件夾

彩蛋

現(xiàn)實世界中讳苦,環(huán)境光可能不只是單一的顏色带膜,現(xiàn)在我們做一個變動,根據(jù)時間來改變環(huán)境光的顏色鸳谜,看看有什么不一樣的效果膝藕。
代碼如下:

 //構(gòu)建一個隨時間改變光照顏色
    float r = sin(self.elapsedTime * 1.2);
    float g = sin(self.elapsedTime * 1.3);
    float b = sin(self.elapsedTime * 1.7);
    
    GLKVector3  lightColor = GLKVector3Make(r, g, b);
    
    GLKVector3 lightAmbient = GLKVector3Make(0.2, 0.2, 0.2);
    GLKVector3 lightDiffuse = GLKVector3Make(0.5, 0.5, 0.5);
    
    lightAmbient = GLKVector3Multiply(lightColor, lightAmbient);
    lightDiffuse = GLKVector3Multiply(lightColor, lightDiffuse);
    
    glUniform3fv(glGetUniformLocation(_esContext.program, "light.ambient"), 1, lightAmbient.v);
    glUniform3fv(glGetUniformLocation(_esContext.program, "light.diffuse"), 1, lightDiffuse.v);
    glUniform3f(glGetUniformLocation(_esContext.program, "light.specular"), 1.0, 1.0, 1.0);

我們這里傳入隨時間改變的顏色進(jìn)去,然后乘到環(huán)境光和漫射光的參數(shù)上咐扭。最終效果如下:


RPReplay_Final1638942312.gif

這里通過改變環(huán)境光芭挽,影響物體最終的顏色輸出,是不是類似呼吸燈的效果蝗肪?
這一步的代碼對應(yīng)文件夾Cube_material-03袜爪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市薛闪,隨后出現(xiàn)的幾起案子辛馆,更是在濱河造成了極大的恐慌,老刑警劉巖逛绵,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀各,死亡現(xiàn)場離奇詭異倔韭,居然都是意外死亡术浪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門寿酌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胰苏,“玉大人,你說我怎么就攤上這事醇疼∷恫ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵秧荆,是天一觀的道長倔毙。 經(jīng)常有香客問我,道長乙濒,這世上最難降的妖魔是什么陕赃? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任卵蛉,我火速辦了婚禮,結(jié)果婚禮上么库,老公的妹妹穿的比我還像新娘傻丝。我一直安慰自己,他們只是感情好诉儒,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布葡缰。 她就那樣靜靜地躺著拘悦,像睡著了一般殖氏。 火紅的嫁衣襯著肌膚如雪赘淮。 梳的紋絲不亂的頭發(fā)上捌治,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天靖秩,我揣著相機(jī)與錄音娃循,去河邊找鬼胎围。 笑死欲低,一個胖子當(dāng)著我的面吹牛米者,可吹牛的內(nèi)容都是我干的韭畸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蔓搞,長吁一口氣:“原來是場噩夢啊……” “哼胰丁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喂分,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤锦庸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蒲祈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甘萧,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年梆掸,在試婚紗的時候發(fā)現(xiàn)自己被綠了扬卷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡酸钦,死狀恐怖怪得,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卑硫,我是刑警寧澤徒恋,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站欢伏,受9級特大地震影響入挣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜硝拧,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一径筏、第九天 我趴在偏房一處隱蔽的房頂上張望风皿。 院中可真熱鬧,春花似錦匠璧、人聲如沸桐款。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魔眨。三九已至,卻和暖如春酿雪,著一層夾襖步出監(jiān)牢的瞬間遏暴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工指黎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留朋凉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓醋安,卻偏偏與公主長得像杂彭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吓揪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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