OpenGL關(guān)于片段著色器是如何進(jìn)行線性插值的疑惑?

OpenGL的官方文檔中有一個(gè)例子:

image
#version 330 core
layout (location = 0) in vec3 aPos;   // 位置變量的屬性位置值為 0 
layout (location = 1) in vec3 aColor; // 顏色變量的屬性位置值為 1

out vec3 ourColor; // 向片段著色器輸出一個(gè)顏色

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // 將ourColor設(shè)置為我們從頂點(diǎn)數(shù)據(jù)那里得到的輸入顏色
}

意思是在頂點(diǎn)著色器中猛拴,傳入3個(gè)頂點(diǎn)的顏色羹铅,最終會生成一個(gè)有漸變色彩的三角形。
剛學(xué)到這個(gè)東西的時(shí)候感覺非常反直覺愉昆,因?yàn)轫旤c(diǎn)著色器實(shí)際上只提供了3個(gè)顏色职员,為什么會生成這么多的顏色并且填滿整個(gè)三角形呢?

官方給的解答是:

這個(gè)圖片可能不是你所期望的那種跛溉,因?yàn)槲覀冎惶峁┝?個(gè)顏色焊切,而不是我們現(xiàn)在看到的大調(diào)色板。這是在片段著色器中進(jìn)行的所謂 片段插值(Fragment Interpolation) 的結(jié)果芳室。當(dāng)渲染一個(gè)三角形時(shí)专肪,光柵化(Rasterization)階段通常會造成比原指定頂點(diǎn)更多的片段。光柵會根據(jù)每個(gè)片段在三角形形狀上所處相對位置決定這些片段的位置堪侯。
基于這些位置嚎尤,它會插值(Interpolate)所有片段著色器的輸入變量。比如說伍宦,我們有一個(gè)線段芽死,上面的端點(diǎn)是綠色的乏梁,下面的端點(diǎn)是藍(lán)色的。如果一個(gè)片段著色器在線段的70%的位置運(yùn)行收奔,它的顏色輸入屬性就會是一個(gè)綠色和藍(lán)色的線性結(jié)合掌呜;更精確地說就是30%藍(lán) + 70%綠滓玖。
這正是在這個(gè)三角形中發(fā)生了什么坪哄。我們有3個(gè)頂點(diǎn),和相應(yīng)的3個(gè)顏色势篡,從這個(gè)三角形的像素來看它可能包含50000左右的片段翩肌,片段著色器為這些像素進(jìn)行插值顏色。如果你仔細(xì)看這些顏色就應(yīng)該能明白了:紅首先變成到紫再變?yōu)樗{(lán)色禁悠。片段插值會被應(yīng)用到片段著色器的所有輸入屬性上念祭。

也就是說在渲染管線中,進(jìn)行片段著色之前碍侦,可能會對要渲染的每一個(gè)像素進(jìn)行插值粱坤。但是它是如何進(jìn)行插值的呢?
起初我認(rèn)為瓷产,在片段著色器里站玄,會首先渲染這個(gè)圖形每個(gè)頂點(diǎn)的顏色,然后進(jìn)行線性插值濒旦,最后渲染每一個(gè)像素的顏色株旷。

直到我學(xué)到漫反射之后,感覺我的理解有點(diǎn)不對:
如圖尔邓,利用OpenGL渲染出來的漫反射圖:


1.png

片段著色器代碼如下:

#version 330 core   
out vec4 FragColor;

in vec3 FragPos;
in vec3 Normal;

uniform vec3 objColor;
uniform vec3 ambientColor;
uniform vec3 lightPos;
uniform vec3 lightColor;

void main(){    
    vec3 lightDir = normalize(lightPos - FragPos);
    vec3 diffuse = max(dot(lightDir,Normal),0) * lightColor;//點(diǎn)乘  
    FragColor = vec4((ambientColor + diffuse) * objColor,1.0);
}

我把光源設(shè)置在第一個(gè)立方體中心前面一點(diǎn)的位置晾剖,渲染出來了比較真實(shí)的光照效果。
你可能會注意到梯嗽,正方體中心位置會比頂點(diǎn)周圍的像素要亮得多齿尽。如果按照我之前的理解,光柵化之后灯节,片段著色器會先渲染每個(gè)頂點(diǎn)的顏色循头,然后插值運(yùn)算每個(gè)像素的顏色,那么結(jié)果肯定和渲染出來的不同显晶。
因?yàn)榘秧旤c(diǎn)帶入到片段著色器計(jì)算的話贷岸,每個(gè)頂點(diǎn)的顏色是用(ambientColor + diffuse) * objColor即環(huán)境光和漫反射計(jì)算出來的,由于光源和每個(gè)頂點(diǎn)的夾角相同磷雇,所以計(jì)算出每個(gè)頂點(diǎn)的顏色相同偿警,然后進(jìn)行插值運(yùn)算填充像素的話,那么渲染出來的結(jié)果肯定是這個(gè)立方體正對著我們的一面都是同一種的顏色唯笙,不會出現(xiàn)中心要亮一點(diǎn)的情況螟蒸。

這時(shí)候我突然發(fā)現(xiàn)盒使,之前的理解肯定有問題,于是又花了些時(shí)間退回去看渲染管線的一些知識七嫌。
我認(rèn)為OpenGL從頂點(diǎn)著色器 -> 片段著色器可能會經(jīng)歷這么一個(gè)過程:
這里貼上頂點(diǎn)著色器代碼:

#version 330 core                                       
layout (location = 0) in vec3 aPos;   // 位置變量的屬性位置值為 0 
layout (location = 3) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main(){                                            
    gl_Position = projection * view * model * vec4(aPos, 1.0); // 注意乘法要從右向左讀
    FragPos = (model * vec4(aPos, 1.0)).xyz;
    Normal = mat3(model) * aNormal;
}

OpenGL的片段著色器在進(jìn)行渲染之前少办,實(shí)際上會對out里面的數(shù)據(jù),例如FragPos,Normal進(jìn)行線性插值例如頂點(diǎn)(1,0,0,1)和(3,0,0,1)诵原,就會對中間的像素插值(2,0,0,1)英妓。由于一個(gè)面上的頂點(diǎn)法向量都是相同的,所以Normal進(jìn)行插值的時(shí)候绍赛,同一個(gè)面上生成的值都是相同的蔓纠。
在片段著色器中,會對面一個(gè)插值出來的像素計(jì)算它的顏色吗蚌,進(jìn)行(ambientColor + diffuse) * objColor的計(jì)算腿倚,由于每個(gè)像素點(diǎn)FragPos不同,所以會計(jì)算出如上圖那樣立方體面中心很亮的結(jié)果蚯妇,而不是像我理解那樣先計(jì)算正方形面的四個(gè)頂點(diǎn)敷燎,然后進(jìn)行插值渲染,這樣就會出現(xiàn)一個(gè)顏色都相同的立方體面箩言。

以上知識本人的一點(diǎn)理解硬贯,可能是錯(cuò)的,初學(xué)OpenGL分扎,感覺它還是蠻硬核的澄成,很多問題都要糾結(jié)很久...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市畏吓,隨后出現(xiàn)的幾起案子墨状,更是在濱河造成了極大的恐慌,老刑警劉巖菲饼,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肾砂,死亡現(xiàn)場離奇詭異,居然都是意外死亡宏悦,警方通過查閱死者的電腦和手機(jī)镐确,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饼煞,“玉大人源葫,你說我怎么就攤上這事∽┣疲” “怎么了息堂?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我荣堰,道長床未,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任振坚,我火速辦了婚禮薇搁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渡八。我一直安慰自己啃洋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布呀狼。 她就那樣靜靜地躺著裂允,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哥艇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天僻澎,我揣著相機(jī)與錄音貌踏,去河邊找鬼。 笑死窟勃,一個(gè)胖子當(dāng)著我的面吹牛祖乳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秉氧,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼眷昆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汁咏?” 一聲冷哼從身側(cè)響起亚斋,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎攘滩,沒想到半個(gè)月后帅刊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漂问,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年赖瞒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚤假。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栏饮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磷仰,到底是詐尸還是另有隱情袍嬉,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布芒划,位于F島的核電站冬竟,受9級特大地震影響欧穴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泵殴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一涮帘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笑诅,春花似錦调缨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妇多,卻和暖如春伤哺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背者祖。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工立莉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人七问。 一個(gè)月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓蜓耻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親械巡。 傳聞我的和親對象是個(gè)殘疾皇子刹淌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359