D3D12 不同格式纹理的动态索引

D3D12 Dynamic indexing of textures with different formats

在着色器模型 5.1 中,我们可以像这样对纹理使用动态索引:

Texture2D textures[5] : register(t0)
PixelShader(Input p) : SV_TARGET
{
     float4 color = textures[0].Sample(someSampler, p.UV);
     return color;
}

这里假设所有贴图都有4个通道(rgba)。但是,当我的纹理数组是 BC3 (rgba)、BC4(单通道 R)、BC5(双通道 RG)等不同格式的混合时,我不知道如何采样。例如,如果是 BC4,我可以尝试

float R = textures[0].Sample(someSampler, p.UV).r;

但这不会跳过三个纹素吗?

这不是 'texture array'。这只是声明 5 个单独绑定的纹理的一种方法,语法允许您使用 select t0t1 的索引。一个'texture array'声明如下:

Texture2DArray textures : register(t0);

纹理数组中的每个纹理必须是相同的格式(它是一个资源),并且您使用 float3 对其进行索引以进行采样。

float4 color = textures.Sample(someSampler, float3(p.UV,0) );

你在上面所做的与以下内容基本相同:

Texture2D texture0 : register(t0);
Texture2D texture1 : register(t1);
Texture2D texture2 : register(t2);
Texture2D texture3 : register(t3);
Texture2D texture4 : register(t4);

因此,每个贴图的格式是完全独立的,代码在这里:

float R = textures[0].Sample(someSampler, p.UV).r;

这只是在 t0 中正常采样纹理,return 只是红色通道。对于 BC4,这将导致硬件解压缩正确的 4x4 块(或块,具体取决于 UV 和采样器模式),以及 return 重建的红色通道。

If you are new to DirectX and HLSL, I strongly recommend not using DirectX 12 to start. It's a fairly unforgiving API designed for graphics experts, so you should consider starting with DirectX 11 instead. The APIs both drive the same hardware, they just do it with different programmer abstractions. DirectX 12 documentation also generally assumes you are already an expert with DirectX 11 anyhow and the HLSL usage is basically the same (with the addition of programmatic control over root signatures). See DirectX Tool Kit for DirectX 11 and DirectX 12.

HSLS 着色器模型 5.1 非常混乱,因为您在 "texture array" 和 "texture array"...

之间有区别

第一个意思是DX10出现的那个,一个纹理资源由多个切片组成,着色器可以在切片中索引。主要限制是每个切片必须共享大小和格式。

第二个意思,像DX12或者Vulkan用API介绍的比较接近"an array of textures"。您现在可以将多个资源对象分组到一个描述符数组中。着色器可以通过动态索引自由使用它们中的任何一个。纹理数组的约束被解除。一个限制是使用 NonUniformIndex 内在函数让驱动程序修复 GPU 可能具有的索引限制。

至于你原来的问题m,然后由你知道纹理在哪里,如果你将纹理与BC4和BC7这样的格式分组,那可能是因为一个是反照率而另一个可能是光泽地图。您的着色器将为它读取的内容赋予语义。但是,如果您希望 BC4 纹理扩展为 RRRR 而不是默认的 R001,您可以在着色器资源视图中使用组件映射。