對(duì)模型剖切是通過設(shè)置scene或者material的clippingPlanes實(shí)現(xiàn)的;
如果設(shè)置了材質(zhì)的clippingPlanes,shader的頂點(diǎn)著色器和片元著色器都會(huì)加入相應(yīng)邏輯的代碼;
1、首先在頂點(diǎn)著色器里加入以下代碼,給vClipPosition賦值,并傳入片元著色器,這里用的是相機(jī)坐標(biāo)系里的值,沒有用世界坐標(biāo)系里的值,這可能是因?yàn)樽儞Q矩陣可能改變法線的朝向,因此要將法線和頂點(diǎn)都統(tǒng)一到相機(jī)坐標(biāo)系里;
#if 1 > 0
vClipPosition = -mvPosition.xyz;
#endif
if語句里的1表示的是clippingPlanes的個(gè)數(shù),編譯shader之前會(huì)被動(dòng)態(tài)替換;
2、到片元著色器里,有如下邏輯:
#if 1 > 0
vec4 plane;
plane = clippingPlanes[ 0 ];
if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;
#if 1 < 1
bool clipped = true;
if ( clipped ) discard;
#endif
#endif
同樣道理,里邊有些固定數(shù)值,其實(shí)是在shader編譯之前動(dòng)態(tài)替換的;上述代碼主要是判斷點(diǎn)落在了平面的哪一測(cè),如果不在指定的一側(cè),就discard,不繪制;
Three.js里的Plane用的是Hessian Normal Form

來描述一個(gè)明面,特別要注意,Plane的構(gòu)造方法里,傳入的距離是帶符號(hào)的,正值表示圓點(diǎn)位于法線方向指向的那一側(cè),負(fù)值表示另一側(cè),見下圖:


注意:上面頂點(diǎn)著色器里,vClipPosition = -mvPosition.xyz,之所以有個(gè)負(fù)號(hào),也是從上面Hessian Normal Form表達(dá)式得出的,NX = -P => -NX = P => N*(-X)=P,P是有符號(hào)的距離。在片元著色器里 dot( vClipPosition, plane.xyz ) > plane.w,plane.xyz和plane.w都是經(jīng)過法線矩陣變換后的值,不是構(gòu)造Plane時(shí)候傳入的。