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