常见贴图技术归纳、性能分析以及在引擎中的一些运用

Overview

本文主要针对一些贴图相关的技术以及其在unity中性能开销的相关分析做一些归纳总结。如有不对的地方,请随时纠正探讨。

Magnification

当屏幕像素的大小大于贴图的大小时所采用的反走样算法,一共有四种主流的过滤方式。

邻近点过滤 nearest neighbor filtering

选择中心点最接近纹理坐标的那个像素,也是最简单的纹理过滤方式,只需要一次采样,效率最高。
在这里插入图片描述

双线性过滤 bi-linear filtering

选择中心点周围的4个纹素加权计算出来,如下图所示,周围的4个纹素是先从水平方向上根据距离加权计算,再根据垂直方向加权计算。
在这里插入图片描述

算法细节

在这里插入图片描述
在这里插入图片描述
其中,s代表像素在横向上的便宜,t代表在纵向上的。
原理上线性过滤需要获取4个纹素,但是现代的GPU硬件已经支持单个周期内完成线性过滤的采样,换句话说它是一个原子操作,并不会拆分为多次采样再加权计算,它消耗是与邻近过滤相当的。
在实际应用中,并不是邻近过滤方式没有任何用武之地,例如很多对深度的采样,并不希望有不同像素之间的加权效果,否则会引入较大的误差。

三线性过滤 Trilinear filtering

线性过滤 + mipmap技术,在线性过滤的基础上,再从mipmap上选择两层mipmap,做一次加权混合
在这里插入图片描述

mipmap采样的算法在之后的minification部分中也有应用,因此算法是一致的。

算法细节

首先要计算出当前像素在UV的dxdy,用以决定mipmap level
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

各项异性过滤 Anisotropic filtering

在这里插入图片描述

三线性过滤在远程会过于模糊,丢失本不该丢失的细节,而各向异性过滤可以一定程度上部分解决这个问题。
常规的mipmap只在横纵方向上取二分之一进行降采样,忽略了横纵不相同的情况。mipmap算法就是对角线的降采样,如下图所示:
在这里插入图片描述

而经过view port transformation之后,屏幕空间的像素对应的UV可能是任意方向的,如下图所示:
在这里插入图片描述

各向异性原理

引入了各向异性过滤后,对于如上图中一些平行于UV轴但映射并非立方体的纹理的采样进行优化。而对于不平行于UV轴的纹理依然无法解决。对于不平行UV轴的情况,建议在DCC阶段对美术展UV进行规范,比如尽量拆分后正交于UV轴,能很好地限制这种情况的发生。
完整各向异性占用显存的大小是原贴图的三倍。但实际应用中一般会开放给玩家设置,或根据机型的配置灵活的调整。各向异性常见的设置中一般会有X N,这个计算多少次的水平和竖直压缩后的mipmap,N值的不同占用的显存大小也就不同。

各向异性过滤算法细节

在这里插入图片描述
即采样N次,最后再取加权算出结果,采样的次数上限受maxAniso控制。
选择的LOD的计算方法为:
在这里插入图片描述
在这里插入图片描述

各项异性的硬件支持

在OpenGL下,是否支持可以通过EXT_texture_filter_anisotropic扩展来来判断;在Metal下,移动平台A7及以后的处理器都支持各向异性过滤方式

各类过滤的性能开销

从实时开销的角度来说,邻近过滤和线性过滤的纹理采样消耗相似,可认为是一次普通的纹理采样消耗;三线性过滤的纹理采样消耗是普通的2倍;各向异性消耗的采样是普通采样的N倍,N依赖设置的maxAniso和实际的纹理与在屏幕上的水平垂直缩放尺寸,即最大采样层数。

从实时开销的角度分析,采样开销:
邻近过滤/线性过滤,1x;
三线性过滤,2x;
各向异性过滤,Nx(N依赖于设置以及纹理的倾斜角度);

从带宽的角度分析:
邻近过滤/线性过滤,仅需要采样单层即可;
三线性过滤,需要支持mipmap,有两层mipmap的带宽开销;
各向异性过滤,需要支持mipmap,有两层mipmap的带宽开销,而且由于LOD更小,因此产生的带宽开销是高于三线性过滤。
单纯的考虑GPU性能而言,mipmap是带宽友好的技术。

minification

主要解决当贴图UV空间映射的大小大于屏幕空间像素的大小时所采用的策略。参考在magnification中的策略,同样需要使用mipmap技术进行解决。在上一节中这一块已经详细介绍了,下面主要处理一些细节问题。

Mipmap在2个level之间是如何过度的?

四舍五入取得最近的那个d值,或是根据距离2个mipmap的距离进行插值。

DDX/DDY

硬件计算mipmap level时,计算了uv方向上的偏导,而同时我们也可以在shader中使用相同的技术。从下图可以知道mipmap的计算规则。
在这里插入图片描述

dxdy不仅能计算mipmap level,可以计算任意存在的attributes(应该)。

DDX/DDY的计算开销

DDX、DDY的计算基于GPU的并行架构。一般多个shader同时在一个SIMD中执行,因此访问邻近shader的寄存器的开销几乎可以忽略。而且GPU的计算在DX中的表现是以2*2一组一起计算的。

ddx ddy在边界不足4个像素是如何处理的?

在这里插入图片描述

当有上图这种情况时,ddx(1) = 2 - 1, ddy(1) = 3 - 1,而1、3没有被覆盖,2、4被覆盖了。所以这种情况下一般采用的策略是对1和3进行外插(extrapolation),保证他们也有相对合理的插值后的attributes数据,然后再计算ddx,ddy

Mipmap filter

mipmap在unity中有两种常见的滤波方式, box filter和kaiser filter。

box filter

最简单的预滤波,随尺寸减少,mipmap的纹理变得平滑模糊。

kaiser

避免平滑模糊的锐化过滤算法。

gaussian, lanczos

更高级的滤波,由于在unity引擎中没有,暂时略过。

mipmap streaming

在运行时只采样某个级别以下的纹理。根据Unity官方文档的描述,这个功能开启后,unity只会加载需要的mipmap等级。此功能会带来一定的CPU开销,相比常规加载全部mipmap的方式会节约一定的内存。这个计算是基于camera当前的位置的,通过camera的位置来决定哪些是必不可能需要加载的mipmap等级。一般来说如果可以把低级别的mipmap舍弃掉只加载特定高级别以上的mipmap level,可以节约一大部分的内存。

贴图资源性能优化的常见策略

  • 根据贴图是否为srgb勾选unity中贴图设置的srgb选项,如果贴图类型是srgb并且unity工程设置为线性空间工作流时,unity会在计算时将srgb转化为线性空间。着色完成后,再进行一次gamma矫正。因此需要合理规划。
  • 因根据物体占据屏幕的像素大小来选择合适的纹理,这方面可以用工具来实现检测
  • 不同的平台和设备中高低配应该准备多套贴图资源。
  • 选择合适的加载方式,例如流式加载,稀疏纹理,虚拟纹理等。
  • 不能用增加分辨率的方式来增加美术细节,可以引入detail texture来增加细节。(带宽?)
  • 纹理压缩
  • 使用纹理图集,方便静态合批处理,也有利于打包时的数据压缩。这部分最好有好用的工具供美术使用,否则工作效率会下降。
  • 根据平台和目标设备性能以及场景的效果需求选择合适的过滤方式,这一点可以看之前的章节来进一步深化。

各平台常见的纹理压缩格式

在这里插入图片描述

Virtual Textre

主要用来解决大贴图和内存开销问题的贴图加载技术。

SVT

一个很大的Texture将不会全部加载到内存中,而是根据实际需求,将需要的部分加载。与虚拟内存不同的是,它不会阻塞执行,可以使用更高的mipmap来暂时显示,它对基于block的压缩贴图有很好的支持。 基本思路是,会将纹理的mipmap chain分割为相同大小的tile或page,这里的纹理叫虚纹理,然后通过某种映射,映射到一张内存中存在的纹理,这里的纹理是物理纹理,在游戏视野发生变化的时候,一部分物理纹理会被替换出去,一部分物理纹理会被加载。
在这里插入图片描述

这样的机制不仅仅减少了带宽消耗和内存(显存)消耗,也带来了其他好处,比如有利于合批,而不用因为使用不同的Texture而打断合批,这样可以根据需求来组织几何使得更利于Culling,当然合批的好处是states change 变少。LightMap也可以预计算到一张大的Virtual Texture上,用来合批。

Unity

根据官方文档,在HDRP中有支持,和UE4相同,需要使用特定的采样器来进行采样。而且需要现代图形Api例如vulkan metal和dx12等。目前unity仅支持SVT并生成这是一个实验特性,可能会在未来移除= =。并且使用上也有其限制:

  • 不支持umid texture,并且贴图的大小也不能大于16*16。
  • 不支持ab打包…… 无语。
  • 不支持SBP
  • 不支持crunch compression
  • 贴图格式有要求,详情直接看unity文档。
    在这里插入图片描述

UE4

在这里插入图片描述

在这里插入图片描述

Virtual texture在material editor中需要使用专门的采样器进行采样。
在这里插入图片描述

  • 需要注意SVT有最小大小的限制,例如lod4的mipmap的resolution是128128,而SVT的最小resolution也是128128,这种情况下,使用SVT的texture最多只能加载到LOD4,可以通过调整最小resolution来修改。
  • SVT使用随机三线性过滤,和常规三线性过滤的效果不同。有了TAA可以改善这种情况
    在这里插入图片描述

RVT

WIP

Reference

https://zhuanlan.zhihu.com/p/565721594
https://www.bilibili.com/video/BV1X7411F744?p=9&vd_source=6824344cf8b7424dcfb4d5fe10ad5f8f
https://space.bilibili.com/1311706157?spm_id_from=333.337.0.0
http://www.aclockworkberry.com/shader-derivative-functions/#footnote_3_1104
https://www.zhihu.com/question/402802931/answer/2158383316
https://docs.unity3d.com/Manual/TextureStreaming.html
https://www.bilibili.com/video/BV1KK411L7Rg/?spm_id_from=333.337.search-card.all.click&vd_source=6824344cf8b7424dcfb4d5fe10ad5f8f
https://zhuanlan.zhihu.com/p/138484024
https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/VirtualTexturing/
https://docs.unity3d.com/2023.1/Documentation/Manual/svt-streaming-virtual-texturing.html

猜你喜欢

转载自blog.csdn.net/jianfei_zhou/article/details/129476714
今日推荐