Three.js 剖切 clippingPlan

对模型剖切是通过设置scene或者material的clippingPlanes实现的;
如果设置了材质的clippingPlanes,shader的顶点着色器和片元着色器都会加入相应逻辑的代码;
1、首先在顶点着色器里加入以下代码,给vClipPosition赋值,并传入片元着色器,这里用的是相机坐标系里的值,没有用世界坐标系里的值,这可能是因为变换矩阵可能改变法线的朝向,因此要将法线和顶点都统一到相机坐标系里;

#if 1 > 0 
  vClipPosition = -mvPosition.xyz;
#endif

if语句里的1表示的是clippingPlanes的个数,编译shader之前会被动态替换;
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

同样道理,里边有些固定数值,其实是在shader编译之前动态替换的;上述代码主要是判断点落在了平面的哪一测,如果不在指定的一侧,就discard,不绘制;

Three.js里的Plane用的是Hessian Normal Form

image.png

来描述一个明面,特别要注意,Plane的构造方法里,传入的距离是带符号的,正值表示圆点位于法线方向指向的那一侧,负值表示另一侧,见下图:
image.png

image.png

注意:上面顶点着色器里,vClipPosition = -mvPosition.xyz,之所以有个负号,也是从上面Hessian Normal Form表达式得出的,NX = -P => -NX = P => N*(-X)=P,P是有符号的距离。在片元着色器里 dot( vClipPosition, plane.xyz ) > plane.w,plane.xyz和plane.w都是经过法线矩阵变换后的值,不是构造Plane时候传入的。

你可能感兴趣的:(Three.js 剖切 clippingPlan)