Polygon Clipping using DotProduct
写在前面:
本文章为个人学习笔记,方便以后自己复习,也希望能帮助到他人。
由于本人水平有限难免出现错误,还请评论区指出,多多指教。
部分图元和素材来源于网络,如有侵权请联系本人删除。
参考资料与链接会在文章末尾贴出。
=======================================================================
如何去clip一个polygon形状,一个方法是基于一个polygon用stencil buffer去clip。本文则是基于几个自定义的点组成polygon去clip。
1.start from line
polygon clipping,从最开始来说,应该是一条边(线)的两边有不同的处理方法,因此我们先从一条线开始分析。
首先是基于世界空间的计算:
这里要用dot product来计算,因为我们这里是2D vector,而cross product需要两个3D vector。
首先我们有两个点p0p1构成了一条线段,并生成 line dirction和line normal(两垂直向量相乘为0)两个vector,最后计算line normal 和vector to point的dot product,正是在线段左边,0是在线段上,负数在线段右边。
我们可以把fragment shader中的计算封装成一个方法,这样后续增加更多点计算的时候也会方便点。
2. Draw a Polygon of multiple lines
实际上如果规定线段左边为true,需要clip另一边为false,我们同样可以反过来做,看自己需要的效果,重要的是,polygon的每一条边都应该是一样的规定,即“左边为true需要clip”。
这里我们设置顺时针方向3个点,p0p1p2,即构成了一个三角形,三条边,只需要对三条边都做一次判断就好:
但是每次都在shader代码里面改位置有点麻烦,且点的数量是固定的,我们试着暴露变量出去修改:
第一个参数是我们能把polygon所有点放到array中,但是shader不支持dynamic arrays,因此我们事先设定个大小;第二个参数是目前polygon有多少个点。
而在shader中也没有array这个properties,因此我们通过C#脚本来修改:
我们为这个类加两个attribute,ExecuteInEditMode让我们可以在edit mode中update我们的polygon而不用开始游戏;第二个是确保挂在了该脚本的gameobject有Renderer组件。
我们喜欢两个私有成员能暴露在inspector上所以加了SerializeField的attribute。
在UpdateMaterial中我们创建vector4D数组而不是2D的原因是unity api只允许我们传4D,因此第三第四个位置自动转换成0。
然后我们回到shader中去用这个array。
首先我们需要初始化outside triangle的值为0。
然后用一个 for loop来累加所有边计算的结果。
3. Clip and Color the Polygon
我们想clip掉外面保留里面,用clip函数会clip掉负值,即不会渲染值小于0的部分
加上颜色3
以上就完成了一个小的效果,但是有个缺点就是只能表达凸多边形不能表达凹多边形。
参考资料: