Wireframe without Geometry Shader

这篇来讨论一下渲染线框的方法,目前知道的方法有
1、在贴图上画
2、把线框的模型建出来
3、使用geometry shader计算
4、使用图形接口的fill mode
5、使用pTex,每张贴图是一个线框

前两条是美术的方法,要看情况,如果只是单纯的渲染出线框,肯定是希望用程序的方法解决,减少美术工作量,但是有时候对线框的需求有点风格化,比如颜色的渐变,粗细的变化,这样的话还可能还是美术来做效果更好一些。第3条移动端是不支持的,第4条没找到unity中的接口,而且es好像也不支持……第5条会因为面片的形状大小对贴图上的线框做拉伸,导致粗细不均匀,不过可以在屏幕空间上做判断来改善这个问题。

目前这几个方法,125都可以算美术的方法,34移动端不支持,即OpenGL ES3.1及以下版本支持的,那么有没有不需要gs的计算的方法?

最后我自己没想出来,但是在github上找到一个方法,计算代价不大,主要需要额外的uv或模型。
http://github.com/miguel12345/UnityWireframeRenderer

大致讲一下他的思路:
关键在于,重新组织mesh的信息,mesh中有索引数组可以帮助我们组织三角形,取得这个情报后,把它放进顶点的UV,使得shader可以看这个情报。

1、在原物体上挂一个新的GameObject,把原mesh的信息放进新的mesh
2、复制信息时,做一些手脚:将一个三角形的三个点的UV分别设置为00, 01, 10
3、于是就可以根据一个点的uv位置知道它在三角形中什么位置了,而且计算到边的距离运算量很小

但是很容易发现这样有个问题,uv位置只是一个相对位置,如果给这个比例值限定一个固定的阈值的话,假设一个正方形拉长,那么有两条边会变粗,大小不同的三角形粗细也会不一样。而我们的目的是在最后的像素空间上看起来粗细一样。如何解决这个问题呢?

可以使用导数,也就是ddx、ddy函数,来求得屏幕空间相邻两个像素的uv差值。

假设三角形大小是x,uv大小是1,那么导数求得的就是1/x,乘以描边大小假设是3,3/x也是个比例值,就是描边粗细在三角形中的比例,这个值作为uv这个比例值的阈值的话,就不会有变形的问题。

实际实现时,要同时考虑u轴v轴两条轴的影响,使得旋转不变形。具体可以看上面github中的代码。