一宪肖、寫在前面
你沒看錯表制,這篇文章重新發(fā)了。
因為C姐說控乾,之前的版本沒頭沒尾么介。
現(xiàn)在想想,確實有點突兀了阱持。
可編程管線基礎(chǔ)在后面的學(xué)習(xí)中至關(guān)重要夭拌,所以我覺得有必要認認真真優(yōu)化一次魔熏。
昨天朋友跟我說:好漢不提當年勇衷咽,何況當初那么菜雞,你寫公眾號里干啥蒜绽?
我回答說:菜雞怎么了镶骗?菜雞就不是雞了?
每當寫這個系列文章的時候躲雅,腦海中就有一種奇特的畫面鼎姊。
但具體是什么,我抓不住相赁,一種似曾相識卻又恍如隔世的感覺相寇。
我總是忍不住要把自己當初學(xué)Shader時候的窘迫分享出來。
目的是為了激勵大家:沒有人生來就會钮科,但不去學(xué)唤衫,就永遠都不會。
二绵脯、最簡單的shader
在上一篇《Cocos Shader入門基礎(chǔ)二:初識Cocos Shader》中我提到說佳励,以后的Cocos Shader將在builtin-unlit.effect基礎(chǔ)上逐步添加內(nèi)容,漸進式學(xué)習(xí)蛆挫。
但有不少C友反饋:
麒麟子赃承,這就是你說的教程?只是粗淺的介紹了各個部分的含義悴侵,Google翻譯也能做啊瞧剖。
麒麟子,能不能講講基礎(chǔ)知識啊可免,你這么一講抓于,還是啥也不懂啊。
麒麟子巴元,照顧一下新人唄毡咏,麻煩從零開始啦。
于是我做了一個大膽的決定逮刨,刪除不必要的東西呕缭,從最最最最簡單的effect開始堵泽,簡單到缺少任何一行代碼,就跑不起來的地步恢总。
我把它命名為cocos-shader-helloworld.effect迎罗,它將渲染出下面的效果。
它目前很簡單片仿,但隨著教程的進行纹安,它將變得越來越胡里花哨。
為了使大家更好地理解各個細節(jié)砂豌,麒麟子在shader中加了注釋厢岂,請看下圖:
三、可編程管線淺析
麒麟子一直在想阳距,3D可編程管線到底應(yīng)該以什么樣的方式塔粒,什么樣的程度講給大家聽。
看到上面的截圖時我靈機一動筐摘。
我們不如就從上到下卒茬,以講解Cocos Shader的角度,對涉及到的3D管線知識進行講解咖熟。
3.1圃酵、定義部分
在cocos shader effect中,可以定義多個technique,每一個technique主要的屬性就是name和pass馍管。
在上面的cocos-shaer-helloworld.effect中我們定義了一個叫opaque的technique郭赐,且這個technique只有一個pass。
如果你不喜歡咽斧,可以改掉technique的名字堪置,這不會對效果造成任何影響。
3.2张惹、vert函數(shù)(頂點著色器)
在本案例中舀锨,頂點著色器的入口函數(shù)是 vert()。
在pass中宛逗,通過 vert:unlit-vs:vert 引用坎匿。
unlit-vs 就是CCProgram的名字,在一個effect文件中雷激,我們可以定義多個CCProgram替蔬,每一個CCProgram中可以有多個函數(shù),然后根據(jù)配置來決定入口函數(shù)屎暇。
在本文所示例的vert函數(shù)中承桥,我們只做了最基本的位置信息輸出:頂點坐標信息在經(jīng)歷了世界變換,攝像機變換根悼,投影變換后凶异,作為vert函數(shù)的返回值蜀撑。
3.3、頂點坐標從本地到屏幕的經(jīng)過
很多朋友誤以為經(jīng)過投影變換后的坐標就是屏幕坐標剩彬,那是不對的酷麦。
vert函數(shù)輸出的坐標并不是屏幕坐標,在有些書上把這個叫 裁剪坐標喉恋。不管叫什么沃饶,大家記住它就是投影后的坐標就行。
這個投影后的坐標轻黑,為了適應(yīng)不同的顯示設(shè)備糊肤,會做一次規(guī)范化設(shè)備坐標系(NDC)處理。
NDC處理過后苔悦,會進行視口映射轩褐。
視口映射結(jié)束后,才是顯示到窗口上玖详。
麒麟子用拙劣的繪圖能力給大家繪制了下面這張變換圖∏诜恚可以清晰的看到頂點坐標需要經(jīng)歷的變換步驟蟋座。
注:投影變換之后,坐標信息就不受Shader控制了脚牍。
3.4向臀、光柵化
頂點著色器之后,并不會直接傳遞給像素著色器诸狭,而是會先把頂點著色器輸出的東西進行插值券膀、像素化。
這個過程有一個術(shù)語叫:光柵化
如下圖所示驯遇,三角形經(jīng)過光柵化后芹彬,變成了一個個像素。
除了頂點位置信息叉庐,頂點法線舒帮、顏色、紋理坐標等都會先經(jīng)過光柵化陡叠,再傳遞給像素著色器玩郊。
由于所有vert輸出的值都會被光柵化,所以頂點著色器傳遞到像素著色器的法線向量枉阵,在使用的時候译红,記得先normalize,否則會有意想不到的效果兴溜。
關(guān)于光柵化的內(nèi)容侦厚,建議大家多在網(wǎng)上搜索資料看看反璃,有一個更深入的了解。
3.5假夺、frag函數(shù) (像素著色器)
光柵化之后的頂點信息會被傳遞給像素著色器淮蜈。
后期的教程中,我們?yōu)榱藢崿F(xiàn)一些高級效果已卷,其實大部分情況下是對frag函數(shù)的增強梧田。在本文的示例中,我們?yōu)榱吮M可能減少大家的理解成本侧蘸,麒麟子連color都沒有從外部傳遞過來裁眯,直接在代碼中定義了顏色。
大家可以修改frag()函數(shù)中的顏色值來查看像素變化
這里順便說一下讳癌,像素著色器(Pixel Shader)和片元著色器(Fragment Shader)是一個東西穿稳。前者來自于Direct3D圈,后者來自于OpenGL圈晌坤。
3.6逢艘、像素的一生
像素著色器處理之后,像素還會進行一系列的測試和操作骤菠,只有測試都通過的像素它改,才會被寫入到目標緩沖區(qū)中。如下圖所示:
3.6.1商乎、模板測試(Stencil Test)
模板測試會根據(jù)預(yù)先設(shè)置好的模板測試參數(shù)進行工作央拖,并決定是否要丟棄像素。
在本文里鹉戚,麒麟子不打算進一步講模板測試的細節(jié)鲜戒。
如果后面的章節(jié)有用到模板測試的地方,會進行詳細說明抹凳。
如果現(xiàn)在就想了解模板測試的朋友遏餐,請自行搜索。
3.6.2却桶、深度測試(Depth Test)
深度測試需要深度緩沖區(qū)的配合境输,請先查看本文6.4小節(jié)中的深度緩沖區(qū)概念。
深度測試提供了 > >= == < <= != 總是颖系,從不等比較運算符嗅剖,默認是 <=。
當一個像素進入深度測試環(huán)節(jié)時嘁扼,會進行如下操作信粮。
3.6.3、融合 (Alpha Blend)
如果一個像素以上所有測試都通過了趁啸,則會進入融合處理階段强缘。
融合就是我們經(jīng)常說的透明混合督惰。
它會將當前像素的值按照我們設(shè)置好的混合方式,與目標顏色緩沖區(qū)的值進行融合旅掂。
如果沒有開啟Alpha Blend開關(guān)赏胚,則這階段自動跳過。
我們常見的alpha混合因子如src_alpha商虐、one_minus_src_alpha等就是用在這個操作上面的觉阅。
關(guān)于alpha blend參數(shù)細節(jié)和使用技巧,我們會在后面的講解中深入解釋秘车。
3.6.4典勇、寫入幀緩沖區(qū)
最終,像素會被寫入緩沖區(qū)中叮趴。幀緩沖區(qū)有三個:顏色緩沖區(qū)割笙、深度緩沖區(qū)、模板緩沖區(qū)眯亦。
顏色緩沖區(qū)(Color Buffer):
顏色緩沖區(qū)伤溉,故明思意,存儲顏色的緩沖區(qū)搔驼。這個緩沖區(qū)就是我們屏幕上能看到的緩沖區(qū)谈火。
深度緩沖區(qū)(Depth Buffer):
是一個看不見的緩沖區(qū)。
深度緩沖區(qū)存儲的是一個與頂點z值相關(guān)的值(這個z值是攝影后的z值舌涨,由于它處于攝像機空間,由近即遠扔字,所以我們稱它為深度)囊嘉。
這個緩沖區(qū)使我們在渲染非透明物體的時候,不用管先后順序革为,也能保證結(jié)果的正確性扭粱。
大大提高了繪制效率。
眼尖的朋友就會問震檩,透明物體怎么辦呢琢蛤?
透明物體是需要從遠到近進行渲染的,可以搜索“油畫家算法”作進一步研究抛虏。
當然博其,cocos引擎已經(jīng)做了這個排序的事情,不必過于擔(dān)憂迂猴。
如果渲染狀態(tài) 深度寫未開啟慕淡,則不會進行深度緩沖區(qū)寫入。
模板緩沖區(qū)(Stencil Buffer):
這個緩沖區(qū)可以理解為一個標記緩沖區(qū)沸毁,他提供了一些比較運算操作峰髓,用于實現(xiàn)一些特殊效果傻寂。
如果渲染狀態(tài)開關(guān) 模板緩沖未開啟,則不會進行模板緩沖區(qū)寫入
模板緩沖區(qū)的背景知識携兵,建議大家多看其他資料疾掰。
這里只是簡單介紹了顏色緩沖區(qū)、深度緩沖區(qū)徐紧、模板緩沖區(qū)的基本概念静檬,如果要展開來講各個細節(jié),可能夠?qū)懞脦灼恼铝恕?/p>
想要了解更多細節(jié)的朋友浪汪,請自行搜索關(guān)鍵字巴柿。
四、總結(jié)
根據(jù)C友們的反饋死遭,麒麟子在本文中直接將Cocos Shader的學(xué)習(xí)拉回到了原點广恢,真正的從零開始。
雖然本文的cocos-shader-helloworld非常簡單呀潭,但隨著教程的進行钉迷,它會越來越豐富。
它越是華麗钠署,代表你Shader的學(xué)習(xí)越有進步糠聪。
本文也對3D可編程管線做了一個簡要的梳理。
然而由于篇幅有限谐鼎,不可能詳盡地講每一個知識點舰蟆。
好在網(wǎng)絡(luò)上已經(jīng)有很多相關(guān)優(yōu)質(zhì)的文章。
希望大家下來后狸棍,以本文為題綱身害,針對文中提到的各種術(shù)語和關(guān)鍵字進行搜索,去拓展自己的相關(guān)知識草戈。
編程這個事情塌鸯,只要下功夫多練,收獲不會差的唐片。
借賣油翁的一句話:
我亦無它丙猬,但手熟爾!
五费韭、預(yù)告
下一篇茧球,我們將在cocos-shader-helloworld的基礎(chǔ)上做如下操作
為shader添加外部變量
外部變量在Inspector面板上的控制
外部變量在代碼中如何控制
敬請關(guān)注!