如何摆脱 Metal MTLTexture 中的 alpha 通道?

How can I get rid of the alpha channel in a Metal MTLTexture?

在我的 Metal 游戏中,我注意到 none 的纹理有任何透明像素,但 alpha 通道仍然存在。它们都被冗余填充 0xFF 字节。

let TextureDescriptor = MTLTextureDescriptor()
TextureDescriptor.pixelFormat = View.colorPixelFormat
TextureDescriptor.width = 16
TextureDescriptor.height = 16
TextureDescriptor.mipmapLevelCount = 5
TextureDescriptor.textureType = MTLTextureType.type2DArray
TextureDescriptor.arrayLength = 22
TerrainTextures = Device.makeTexture(descriptor: TextureDescriptor)
// Load Textures

View 是定义为 NSViewController view 转换为 MTKView 的全局变量。如果我尝试除 view.colorPixelFormat 之外的任何其他方法,我会遇到诸如纹理变色,甚至根本没有渲染等问题。但这恰好是 bgra8Unorm_srgb,其中 包括 alpha。我想通过简单地删除没有它的纹理的 alpha 通道来减少四分之一的纹理内存。但是我该怎么做呢?如何在没有 alpha 的情况下指定每个像素 3 个字节的 RGB 格式?然后我可以让片段着色器提供一个 alpha 通道,而不是带有一个的纹理?我看了一下here,好像没有24位的格式,请问有什么办法吗?我可以以某种方式指定自定义格式而不是默认格式之一吗?或者我是否必须通过一些拉伸来模拟这一点,例如每个纹理有 3 个纹理,因为我将为每个完整纹理的三个 RGB 通道中的每一个使用每像素 1 8 位纹理?

回答您的问题:

How can I specify an RGB format with 3 bytes per pixel without an alpha?

没有符合您描述的纹理格式。有使用更高精度的压缩 32 位格式,但没有每通道 8 位并适合 24 位的格式,因为这些 24 位格式无论如何都不适合现代硬件。

Can I somehow specify a custom format instead of one of the default formats?

不是,纹理由称为 TPU 的硬件单元处理,您无法真正想出自己的纹理格式

I would be using 1 8 bit per pixel texture for each of the three RGB channels of the each complete texture?

我强烈建议不要这样做,因为实际上有一个纹理缓存,如果您在同一纹理坐标处采样三个不同的纹理,它不知道如何关联它们,您最终会得到一个性能命中.

相反,您有三个选择。

第一个选项有点难做,因为您需要大量基础设施。您可以使用压缩格式,如 ASTC 或 BCn。要了解更多相关信息,今年 WWDC2021 即将举行的演讲名为 Discover Metal 调试、分析和资产创建工具,将于周三 post 举行。

第二个选项是使用备用通道来获取一些有用的信息,例如遮挡、某种掩码或任何特定于您的游戏的域。

第三个选项只是使用每个通道 8 位的 32 位格式,忽略 alpha 或根据需要用 0 或 1 填充它。这是最简单的选项,我建议在进入其他选项之前使用它。