昨天无意中看到群里的好友发的截图里有一个VR/Wireframe的shader,晚上下载了5.6.3的bulit-in看了源代码。 Unity很有良心,直接在代码的开头注释了理论资料。 是NVIDIA的文章。 虽然DX11本身提供了FillMode=D3D11_FILL_WIREFRAME选项,可以直接渲染栅格,但NVIDIA认为这种渲染存在许多问题,并提供了该技术和以前的双PPE 当然,文章中说自己的技术基本上是各方面全面领先的。 我也不会去找以前关于双路径渲染的资料。
总体思路简单明确,只渲染与三角形边缘的距离在一定范围内的像素。 那么,如何知道离像素边缘的距离呢? 通过在Geometry Shader中计算三角形减少空间中每个顶点到其对边的距离,即三角形三条边的高度,可以轻松获得NVIDIA。 两边加倍,面积加倍,除以边长,得到高度:
如果将三条边的高度传递给“fragment shader”,则在光栅化插值后,可以获得其中一个像素离开这三条边的距离。
最后,在“fragment shader”中取最小距离并与预设阈值进行比较,可以获得以下结果:
正如您所看到的,由于锯齿感很严重,NVIDIA为了插值添加了调和函数。
NVIDIA选择22x22x2,取得了以下效果。
最后,将代码更改为,而不是与三条边的距离取最小值
floatmindistancetoedge=min (I.dist [0],max ) i.dist[2],i.dist[2] ) ) i.dist[2];
得到没有对角线的网格。
一波未平
之前写的不画斜线的算法确实蛋疼,而且画的效果也很受挫。 还剩下一点斜线,很难看。 前段时间,突然想到这个东西,决定改,但是智商很急,想法依然简单粗暴:
斜线通常是三角形中一边长度最长的线,索性在GS阶段标记其索引并传递给FS,FS计算最小距离时,根据GS发送的索引排除斜边,可以得到漂亮的正方形边框效果:
但是,代码真的很受挫,无法看到。 GS本身性能不高,让我性能这么低,暂时没有想出特别优雅的实现方法。 继续着to be continue…