|
内置算法的问题
unity的曲面细分,特别是surface shader下开发自由度很低,能做的特殊修改手段较少。但是自带的2种细分方式都有各自的问题。
先看看按UnityDistanceBasedTess
有接缝(必须解决)从最终的屏幕空间看远处比近处细分的更多(算是有性能浪费 一般来说远处的细节不需要超过近处)
UnityDistanceBasedTess 曲面细分的问题
再看下 UnityEdgeLengthBasedTess
没做距离裁剪,性能不行(因为地形一般都会覆盖很长一段距离)
UnityEdgeLengthBasedTess 曲面细分问题
修改思路
经过观察2个算法问题,那么思路就比较明确了,就是要实现一版支持距离剔除的 EdgeLength 算法。
首先找到 buildin的这部分函数 (Tessellation.cginc 文件内)
我们先做一步按距离衰减,临时凑几个参数关系,关键点是让 分母变大的快些 也就是按dist的 x次发,x>1 来计算比如 取1.2。
为什么又要 外面*8 内部/8呢?这是因为直接的pow让远处变的比原来小很多 没有细分的效果.我们只想要变化下降的更快,不是有效距离更近,对比以下的3个函数曲线图可以看到,f2在黄箭头处确实实现了更快下降,但红箭头处值比原来小太多.而f3 就同时满足保持远处有效距离与中部快速下降细分参数.
过小f值 剔除前效果
这样就得到了上图效果,可以发现当f 又远又小的时候,那点细分都几乎是平行线了,这种划分方式对曲面细分效果没帮助。因为中间的区域没得到更多顶点。所以需要再加一句这部分剔除 if (f/ dist <0.06)f = 1;这样就得到下图效果了。
过小f值 剔除后效果
本方案 细分效果
性能对比
原版算法是支持无穷远的,而本方案是支持有限距离,所以计算量和效果本就不同,这个对比数据没多少意义。但是一般项目都不会选择无限距离开启细分,所以调了一版尽量接近原版效果的对比下帧数。
原版UnityEdgeLengthBasedTess 性能
本方案 UnityEdgeLengthBasedTess 性能
法线修正
根据日常经验,任何修改顶点坐标的算法,都会引起normalmap计算的错误. 这是因为离线烘焙normalmap的时候 预想的切线空间是固定的低模.而不是 现在修改后的样子.所以严谨的说,植被的顶点摇摆动画,曲面细分的高度修改,树的半球法线方案.都修改了 切线空间.都应该做法线的修复计算.只是多数情况下这个计算需要额外开销,且小幅度运动下误差不明显,所以很少提及而已.对比下 quixel mixer里 正确的法线输出 与unity的对比.因为他们yz轴定义不同,我用ps交换了gb通道.
quixel mixer里正确的法线效果(交换gb通道后)
unity里 曲面细分+高度置换后 错误的法线数据
这是因为顶点修改后 xz平面变成了 一个斜面,normalmap里 一个蓝色 原本应该往y方向突起方向 ,现在需要改成沿着新法线方向突起的部分.
常见的解决方案是2种
多采样:2次计算出顶点所在的斜面的 斜率,根据这个计算出新的切线方向.多存储:把1的斜率离线存起来,或直接存切线方向.
这2种方法我都不太喜欢,所以就不想动手写这部分代码,下午就开始了技术型划水.划着划着发现了第三种方法.quixel mixer里发现了这个选项,这不就是我需要的吗?不修改切线空间直接修改置换后新空间的法线.不用多采样 也不用额外存储.正是我想要的.验证下效果确实基本正确了.
unity里 曲面细分+高度置换后 用上修正后法线贴图
普通法线(左)与置换贴图产生的法线(右)
法线修复效果对比
开启本方案效果 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|