着色器在 Unity3d 中扭曲或收缩纹理的特定区域

Shader to warp or pinch specific areas of a texture in Unity3d

我在下图中模拟了我想要完成的事情 - 尝试将像素捏向 AR 标记的中心,这样当我覆盖 AR 内容时,AR 标记就不那么明显了。

我正在寻找一些可以参考的示例或教程,以开始学习如何创建着色器来扭曲纹理,但我一无所获。

完成此任务的最佳方法是什么?

这可以使用 GrabPass 来实现。

来自手册:

GrabPass is a special pass type - it grabs the contents of the screen where the object is about to be drawn into a texture. This texture can be used in subsequent passes to do advanced image based effects.

扭曲效果的工作方式基本上是在网格顶部渲染 GrabPass 纹理的内容,但其 UV 扭曲了。这样做的一种常见方法(对于热变形或冲击波等效果)是渲染一个带有法线贴图的广告牌平面,其中法线贴图控制背景样本的 UV 扭曲程度。这通过将法线从世界 space 转换为屏幕 space,将其与强度值相乘,并将其应用于 UV 来实现。这种着色器有一个很好的例子 here。您也可以在技术上使用任何网格并以类似的方式使用其顶点法线进行置换。

除了法线贴图平面之外,实现此效果的另一种方法是使用 Shader.SetGlobalVector 将跟踪器的屏幕-space 位置传递到着色器中。然后,在你的着色器中,你可以计算你的片段和对象之间的向量并使用它来偏移 UV,可能使用一些重映射函数(比如平方距离)。例如,您可以使用 float2 uv_displace = normalize(delta) * saturate(1 - length(delta)).

如果您想准确控制应用此效果的方式和时间,请将 ZTest 和 ZWrite 设置为关闭,然后将渲染队列设置在背景之后但在您的跟踪器之前。

对于 AR 应用程序,可以通过使用相机背景纹理而不是 GrabPass 纹理来避免使用 GrabPass 的性能开销。您可以尝试查看相机背景脚本内部,了解它如何将相机纹理传递给着色器并尝试复制它。

这里有两个视频演示了 GrabPass 的工作原理:

https://www.youtube.com/watch?v=OgsdGhY-TWM

https://www.youtube.com/watch?v=aX7wIp-r48c