开发者生态
morning
纹理的解剖
摘要
Anatomy of a Texture Introduction Last year I had to write code which converted texture data between gaming platforms. Going into it, I seriously underestimated the complexity of texture memory layout...
texture
the
this
will
memory
and
post
which
complexity
details
2026-09-17
1 阅读
约5分钟阅读
Agentlien
字号:
纹理简介的剖析 去年,我不得不编写在游戏平台之间转换纹理数据的代码。深入研究后,我严重低估了纹理内存布局的复杂性。我目前在 505 Games 的一个团队工作,负责将自定义 PC 游戏引擎移植到游戏机上。面临的众多挑战之一是纹理转换。我知道其中有很多复杂性和微妙之处。我孤立地认出了他们中的大多数人。但是,直到我必须编写工作代码来同时处理所有这些细节时,整个复杂性才真正融入其中。所以,我认为这将成为一篇有趣的博客文章!这篇博文将解释纹理内存布局的复杂性,以及为什么它是必要的。这将通过尝试调试控制台纹理每个部分的内存地址计算的人的镜头来完成。由于主题的原因,这篇文章必须增加一点技术性。我将假设您了解编程基础知识、内存布局,并熟悉基本的视频游戏技术和数字图像。在本文中,我们将使用 1024x1024 RGBA 纹理(以 BC7 为例)。为了便于说明,我们使用简单的木材纹理。图 1. 1024x1024 示例纹理 在平台之间转换此纹理需要我们跟踪大量细节。出于本文的目的,我将解释以下内容:块压缩、纹理元素排序、mips 和纹理图块。还有其他细节,例如间距、深度和纹理数组索引。这些主要需要简单的偏移,这有点烦人,但没有添加任何有趣的理论,所以我将忽略它们。如果我们忽略所有这些复杂性并将结果解释为简单的颜色值流,则该图像将如下所示: 图 2. 1024x1024 混沌彩虹噪声 平台细节 如果这篇文章是关于纹理格式的,为什么我要谈论内存位置?我们将讨论的所有细节在平台之间都有一些非常重要的相似点和区别。特别是,纹理被分解为跨平台的相同构建块层次结构。然而,在层次结构的每个级别,这些元素在内存中的顺序可能因平台而异。这意味着给定一个存储纹理的内存区域,在平台之间转换纹理的行为可以看作是为每个元素计算转换后其预期内存地址的问题。我们将主要以与平台无关的方式讨论大多数组件。在需要区分的地方,我们将依赖 DirectX 12 所采取的视图。 理想化视图 鉴于对数字图像的一般了解,人们可能会如何期望在内存中表示 2D 纹理?图像有许多颜色通道,每个颜色通道都有特定的位深度。常见的位深度为 8,即每个通道一个字节。这为我们提供了每种颜色范围 [0,255] 的值。图像包含颜色样本网格,通常跨越两个维度:宽度和高度。对于普通图像,这些样本称为像素。对于纹理,我们将其称为纹素。鉴于此,天真的假设是具有 32 位颜色深度的 RGBA 图像只是从左到右逐行扫描的纹素流,每个纹素表示为四个连续字节:每个通道一个。虽然一些简单的纹理确实可以这样工作,但不幸的是,这与大多数纹理在现代视频游戏中的表示方式相去甚远。原因是性能。应用了多种正交技术,每种技术都会使纹理表示变得复杂,但会提高渲染性能。大多数(例如纹理元素排序和纹理图块)的存在都是为了提高缓存局部性。也就是说,尽最大努力将数据存储为尽可能接近我们期望同时需要的所有其他数据。良好的局部性大大减少了等待内存传输所浪费的时间——这是现代计算机硬件中最昂贵的操作之一。虽然块压缩也有助于局部性,但它主要通过减少内存中的纹理大小来提高内存传输速度。最后,我们的 mips 通过提前多个步骤对整个纹理进行下采样,大大降低了渲染成本 - 使我们能够避免在想要对周围区域中的所有纹理像素进行平均时需要的许多昂贵的纹理样本。从跨平台调试纹理加载的人的角度来看,这些技术中的每一项都是需要跟踪的另一个问题。单个纹素让我们看一下在典型的现代视频游戏纹理中实际的纹素是如何表示的。为简单起见,我们假设原始图像是 RGBA,每个通道 8 位,如上所述。如果未压缩,每个纹素总共为 32 位(4 字节)。然而,大多数现代纹理都使用块压缩。块压缩缩小了t的内存大小
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱