Cocos Shader入门基础六:平面、双面材质与自定义裁剪面 来自虚空的龙
麒麟子今天要用空間幾何的方式,將難以理解的代數(shù)推導(dǎo)過(guò)程直觀的解釋清楚。
目標(biāo)是:零基礎(chǔ)也能懂!!!!
你是否也曾好奇?
如果要渲染一片樹(shù)葉,但樹(shù)葉的兩個(gè)面的外觀通常是不同的,如何做到正反面效果不一樣呢?
如果要渲染像下圖中某個(gè)對(duì)象的一部分,又當(dāng)如何做呢?
細(xì)節(jié)指引: 圖中,處于虛空連接口背后的龍是看得見(jiàn)的,從虛空連接口鉆出來(lái)的龍只能看到一部分身體。
3D 圖形管線在進(jìn)行背面裁剪的時(shí)候,是如何判斷一個(gè)三角形是正對(duì)攝像機(jī)還是背對(duì)攝像機(jī)的呢?如下圖所示:
麒麟小貼士: 背面裁剪是圖形管線在vs之后和fs之前做的一次預(yù)剔除處理。
通過(guò)背面裁剪,圖形管線可以在渲染模型的時(shí)候,剔除背對(duì)著我們的面,(比如一個(gè)正對(duì)著我們的人物模型,他的背面),以提升渲染性能。
看完本文后,你將掌握以下知識(shí)點(diǎn):
- 3D 平面表示法
- 正背面判定
- 自定義裁剪面
- 雙面材質(zhì)
三維空間平面表示法
在3D游戲編程相關(guān)的數(shù)學(xué)書(shū)里,我們可以很容易找到上圖中的內(nèi)容。
它用代數(shù)的方式解釋了為什么可以用 Ax + By + Cz + D = 0 來(lái)表示平面。
A,B,C 是平面的單位化法向量,決定了平面的正方向,D 為坐標(biāo)原點(diǎn)到平面的距離的相反數(shù)。
將一個(gè)點(diǎn)從原點(diǎn)朝向量 (A,B,C) 正方向移動(dòng) -D 的距離,可以得到平面上的一個(gè)點(diǎn),因此這個(gè)表示法被稱(chēng)為:點(diǎn)法式。
麒麟小貼士: 許多教材中,對(duì)矩陣運(yùn)算和相關(guān)公式都是做的代數(shù)推導(dǎo),晦澀難懂。但數(shù)學(xué)是對(duì)事物規(guī)律的體現(xiàn),代數(shù)推導(dǎo)不是唯一解。
對(duì)于 3D 圖形學(xué)中的諸多運(yùn)算,可以使用空間幾何來(lái)推導(dǎo)。空間幾何可以使我們理解起來(lái)更加簡(jiǎn)單直觀。
像反射公式、鏡像矩陣、坐標(biāo)系轉(zhuǎn)換、投影矩陣等與平面相關(guān)的原理,大家不妨試試用幾何原理理解一次。
接下來(lái),我們嘗試著用空間幾何的方式理解一次平面公式(可能需要一些空間想象力):
1、在原點(diǎn)處,向任意方向 (A,B,C) 發(fā)射出一條射線,則這條射線的起點(diǎn)為記 P0(0,0,0),方向記為 Direction(A,B,C)。
2、我們發(fā)現(xiàn),這條射線可以確定一個(gè)唯一的面:經(jīng)過(guò)原點(diǎn)且垂直于條射線方向。 那么 Direction(A,B,C) 恰好就是這個(gè)面的法向量。
3、將這個(gè)射線的起點(diǎn)沿 Direction(A,B,C) 正向或者負(fù)向移動(dòng),可以調(diào)節(jié)它在空間中的位置。 假設(shè)我們移動(dòng)到了點(diǎn) P0(x0,y0,z0),由投影原理可知,此時(shí)射線起點(diǎn)到原點(diǎn)的距離 d 的計(jì)算方式為:
- d = dot(Direction,P0)
- => d = A * x0 + B * y0 + C * z0
此種情況下,我們依然可以得到一個(gè) 經(jīng)過(guò)點(diǎn) P0 且與 Direction 垂直的唯一面。
4、由于 Direction 是空間中任意方向,P0 是射線上的任意點(diǎn),我們可以得到一個(gè)結(jié)論: 一個(gè)向量和一個(gè)距離坐標(biāo)系原點(diǎn)的值可以用來(lái)表示三維空間中的任意平面。
5、如果一個(gè)點(diǎn) P(x,y,z) 在平面上,可知:
- Ax + By + Cz = d
- => Ax + By + Cz - d = 0
6、不難看出 Ax + By + Cz 剛好是 Direction 與 P 的點(diǎn)乘,而在 3D 空間運(yùn)算中,在參與矩陣運(yùn)算時(shí),點(diǎn)的表示法為 P(x,y,z,1)。
因此, 若將平面記作四維向量 Plane(A,B,C,D) 其中 (D = -d),則恰好滿足點(diǎn)乘運(yùn)算規(guī)則,也完全符合代數(shù)推導(dǎo)結(jié)果:Ax + By + Cz + D = 0。
7、每個(gè)平面,都會(huì)將空間一分為二,我們將法線方向的空間視為平面的正面,法線反方向的空間視為平面的背面。
正背面的判定
3D 模型中,每一個(gè)面,都可以用一個(gè)法線來(lái)表示朝向。如上圖所示,紫色的圓錐指向的方向即為法線方向。
由于點(diǎn)乘的規(guī)律 (夾角小于90度時(shí)為正,大于90度時(shí)為負(fù)) 剛好符合判斷機(jī)制,所以我們通常采用點(diǎn)乘進(jìn)行一些正負(fù)向的判斷。
由點(diǎn)乘規(guī)則可知:
- 當(dāng) dot(Plane,P) > 0 時(shí),點(diǎn)在平面正面;
- 當(dāng) dot(Plane,P) = 0 時(shí),點(diǎn)在平面上;
- 當(dāng) dot(Plane,P) < 0 時(shí),點(diǎn)在平面背面。
雙面材質(zhì)
有了上面的關(guān)于平面的基礎(chǔ)知識(shí),雙面材質(zhì)的實(shí)現(xiàn)就非常易于理解了。
實(shí)現(xiàn)雙面材質(zhì)需要注意三點(diǎn):
1、設(shè)置材質(zhì)的 CullMode 為 None ,如下圖所示:
2、根據(jù)朝向判斷采用正面還是背面的貼圖和顏色
3、當(dāng)為背面時(shí),翻轉(zhuǎn)法線,才能確保光照正確,如下圖所示:
最終實(shí)現(xiàn)的效果如下:
應(yīng)用場(chǎng)景
雙面材質(zhì)可以應(yīng)用在一些需要雙面顯示且雙面材質(zhì)不同的地方,包括但不限于:
- 人物衣服、裙子、飄帶里外
- 單向透光玻璃
- 闊葉植被(如芭蕉樹(shù)、椰子樹(shù)等)
- 布料、紙張等特殊展示場(chǎng)合
自定義裁剪面可以應(yīng)用在一些需要剔除部分物體的地方,包括但不限于:
- 實(shí)時(shí)水面、鏡面渲染
- 模型特效
- 因功能導(dǎo)致的特殊渲染需求
自定義裁剪面
自定義裁剪面算是平面最基礎(chǔ)的應(yīng)用,它的思路與背面剔除很接近:
1、在 Shader 中自定義一個(gè)平面
在Shader中定義平面非常簡(jiǎn)單,只需兩步:
- 在 properties 中添加一個(gè) clipPlane 屬性
- 在 uniform 中聲明一個(gè) vec4 clipPlane。
2、剔除平面背后的內(nèi)容
使用 dot 進(jìn)行平面判定,若位置處于平面背后,則使用 discard 指令進(jìn)行剔除,如下圖所示:
為了更好地展示裁剪效果,麒麟子寫(xiě)了一個(gè)虛空飛龍入侵世界的 DEMO。
天空中出現(xiàn)了另一個(gè)時(shí)空與這個(gè)世界的連接口,龍群從虛空連接口陸續(xù)飛出并在連接口盤(pán)旋,效果如下所示:
自制實(shí)用Shader免費(fèi)分享-來(lái)自虛空幻境的飛龍
DEMO
相關(guān)源碼目錄: CocosShader入門(mén)基礎(chǔ)-DEMO/assets/tutorial_6
免費(fèi)下載地址: https://store.cocos.com/app/detail/3521
總結(jié)
以上是生活随笔為你收集整理的Cocos Shader入门基础六:平面、双面材质与自定义裁剪面 来自虚空的龙的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 两个平面的位置关系和判定方程组解_高中必
- 下一篇: 平面直角坐标系中的旋转公式_巧用隐圆求解