Clipping a Model with a plane
写在前面:
本文章为个人学习笔记,方便以后自己复习,也希望能帮助到他人。
由于本人水平有限难免出现错误,还请评论区指出,多多指教。
部分图元和素材来源于网络,如有侵权请联系本人删除。
参考资料与链接会在文章末尾贴出。
=======================================================================
1 Define Plane
我们首先在C#脚本中定义一个Plane,并将其一些信息传递给shader。
[ExecuteAlways]这个attribute可以让脚本在editor mode下也能work。
我们创建了一个vector4,把新平面的法线放在xyz同道中人,第四个通道代表Plane到原点的距离。
[ExecuteAlways] public class ClippingPlane : MonoBehaviour { // material we pass the values to public Material mat; void Update() { // create plane Plane plane = new Plane(transform.up, transform.position); // transfer values from plane to vector4 Vector4 planeInfo = new Vector4(plane.normal.x, plane.normal.y, plane.normal.z, plane.distance); // pass vector to shader mat.SetVector("_Plane", planeInfo); } }
我们将此添加到一个empty object中,并将我们的材质应用于相应的变量
2 Clip Plane
假设我们希望将位于Plane上方的部分给clip掉,那么表达这个上方自然是Plane的normal了,判断模型表面上的点是否位于Plane上方我们可以用点乘,如果值大于0则为上方,等于0就是在Plane上,负数则在Plane下方。然后将值作为颜色输出。
float4 frag (v2f i) : SV_Target { float distance = dot(i.posWS,_Plane.xyz); float4 finalCol = distance; return distance; }
但是移动Plane的poisition却不会发生变化因为我们目前没有将相关变量加入计算,这时候就要用到_Plane的第四个通道plane.distance。
float4 frag (v2f i) : SV_Target { float distance = dot(i.posWS,_Plane.xyz); float4 finalCol = distance + _Plane.w; return finalCol; }
接下来我们可以通过clip函数裁剪Plane上方
float4 frag (v2f i) : SV_Target { float4 var_tex = tex2D(_MainTex,i.uv); float distance = dot(i.posWS,_Plane.xyz); distance += _Plane.w; clip(-distance); float4 finalCol = -distance * var_tex; return finalCol; }
2 Show Inside
两个新问题:
一是没有渲染模型背面,因此我们把 Cull 关掉
二是横切面没有渲染
现在我们可以看到头部内部,法线仍然指向模型外部,我们可能不想看到头部内部。
我们希望区分出内表面和外表面之间,为了确定我们是在渲染内部表面还是外部表面,我们在fragment shader输入参数中加入新参数facing并给它VFACE的semantic,1表述外面,-1表示里面
因为之后要将值用于线性插值之类的东西,我们将其值映射在 0 到 1 的范围内。
现在我们可以区分模型外面和里面,我们可以让模型内部有单独的颜色:
float4 frag (v2f i,float facing : VFACE) : SV_Target { float4 var_tex = tex2D(_MainTex,i.uv); float distance = dot(i.posWS,_Plane.xyz); distance += _Plane.w; clip(-distance); facing = facing * 0.5 + 0.5; float4 finalCol = lerp(_InsideColor,-distance * var_tex,facing); return finalCol; }
参考链接: