Practical Rendering and Computation with Direct3D 11
+ -

2D纹理

2024-06-17 4 0

我们将探索的第二种纹理类型是2D纹理。由于这种纹理类型与标准2D图像布局密切相关,因此它通常是使用最广泛的纹理类型之一。此资源被组织为二维元素网格,其中每个元素都是DXGI_FORMAT枚举的成员。2D纹理的各种子资源形式如图2.31所示。
153442264022
如图2.31所示,这些纹理以与ID纹理类似的方式支持mip贴图级别和纹理阵列的使用。但是,它们也支持多采样源来实现MSAA。这是唯一允许多重采样的纹理资源类型,因此是一种非常重要的资源类型。

使用2D纹理

二维纹理是Direct3D 11中使用的主要纹理资源。因此,它们在实时渲染应用程序中有许多不同的用途。第一个也是最明显的用途是渲染目标。Direct3D 11渲染管道是任何实时渲染软件的主干,需要一个渲染目标来接收在其中执行的所有计算的结果。此外,在这个渲染过程中,2D纹理通常也用于深度/模版目标,因为它们和深度/模板目标需要在大小和维度上匹配。一旦执行了完整的场景渲染,渲染目标的内容就会显示在所需的输出窗口中,以便在屏幕上查看。在本书的剩余部分中,我们将多次看到这种使用模式。

在标准渲染和深度目标之外,2D纹理通常用于将曲面特性应用于正在渲染的几何体。例如,如果正在渲染砖墙,则通常以在渲染过程中读取的2D纹理提供砖的颜色。提供的表面特性也不一定需要局限于表面的颜色。在现代渲染系统中,使用所谓的法线贴图修改曲面法线向量是非常常见的。这是一个提供3D矢量来表示曲面法线的纹理,其中X、Y和Z坐标存储在纹理的R、G和B通道中。还有其他特性被编码到纹理中,例如表面光泽度、位移和发射率。听到这些类型的纹理被称为贴图是相当常见的。例如,上面提到的纹理将被称为光泽贴图、置换贴图或发射率贴图。

除了上述每对象使用之外,执行场景渲染的后处理以提高向用户呈现的输出的质量也变得越来越重要。在这些情况下,输出渲染被用作各种算法的输入,这些算法进一步处理图像或将图像与其他信息组合以某种方式增强图像。第10章中的算法演示了如何执行。

创建2D纹理

D纹理的创建与ID纹理的情况非常相似。除了添加额外的尺寸规格外,还添加了一个额外的结构参数,以确定要在纹理中使用的多样本级别。纹理是使用ID3DDevice::CreateTexture2D()方法创建的,该方法将指针指向3D11_TEXTURE2D_DESC结构,如清单2.28所示。

typedef struct D3D11_TEXTURE2D_DESC {
  UINT             Width;
  UINT             Height;
  UINT             MipLevels;
  UINT             ArraySize;
  DXGI_FORMAT      Format;
  DXGI_SAMPLE_DESC SampleDesc;
  D3D11_USAGE      Usage;
  UINT             BindFlags;
  UINT             CPUAccessFlags;
  UINT             MiscFlags;
} D3D11_TEXTURE2D_DESC;

typedef struct DXGI_SAMPLE_DESC {
  UINT Count;
  UINT Quality;
} DXGI_SAMPLE_DESC;

如上所述,这种结构与用于1D纹理再现的结构非常相似。纹理的大小由Width和Height参数指定,mip贴图级别和数组切片的数量分别在MipLevels和ArraySizeelements中指定。纹理格式的操作方式也与1Dtexture相同,并且必须设置为DXGI_format枚举的成员。SampleDesc参数是一种结构,用于描述将与2D纹理一起包含的多重采样特征。它包含两个成员:计数和质量。Count参数指定要包含在纹理中的子采样数,而Quality参数表示用于将子采样解析为单个像素值的模式和算法。

质量级别是供应商特定的度量标准,它可能支持也可能不支持多个质量级别。由于对各种质量级别的支持由GPU制造商决定,因此应用程序必须查询特定纹理重新格式化和采样计数的可用质量级别。这是使用ID3DllDevice::CheckMultisampleQualityLevels()方法执行的。清单2.29中显示了该方法的一个示例用法。

UINT NumQuality;
//获取多重采样期间可用的质量级别数。
HRESULT hr = m_pDevice->CheckMultisampleQualityLevels(DXGI_F0RMAT_R8G8B8A8_UNORM, 4, &NumQuality );

在这个例子中,我们可以看到所需的格式是DXGI_F0RMAT_R8G8B8_UNORM,所需的样本数是4。可用的质量级别在NumQuality变量中返回。如果结果为0,则不支持该特定格式和样本计数。如果该值为1或更大,则可以使用任何质量级别,最高可达上述2D纹理描述结构中的返回值。需要注意的是,如果返回n,则应在样本描述结构中使用n-1的值!

Usage、BindFlags和CPUAccess参数是根据本章开头指定的选项选择的,并定义了纹理资源的使用位置和方式。

最后,我们有MiscFlags。下面列出了与2D纹理相对应的标志:

  • D3D11_RESOURCE_MISC_GENERATE_MIPS
  • D3D11_RES0URCE_MISC_RES0URCE CLAMP
  • D3D11_RESOURCE_MISC_TEXTURECUBE

前两个标志具有与1D纹理情况相同的行为。如果纹理的顶级已被写入为渲染目标,则mipsgeneration标志允许自动填充纹理的mip贴图级别,而资源钳制标志提供了一种机制来手动控制哪些mip贴图等级必须驻留在视频内存中。

15432775810
纹理立方体标志对于2D纹理类型是唯一的。该标志表示用六个纹理切片创建的2D纹理可以用于同时生成立方体映射的所有六个面。立方体贴图是六个纹理的集合,可以使用位于立方体中心的三个分量向量对其进行采样,返回该向量所截断的纹理元素。如图2.32所示。内部采样函数可用于使用这种特定类型的纹理资源对象,我们将在本节稍后详细介绍。

创建纹理的另一个参数是要加载到资源中的初始数据。这提供了D3D11_SUBRES0URCE_DATA点,它表示这些结构的阵列,每个子源有一个结构。初始化资源的数据布局如图2.33所示。如果纹理是多采样的,则初始数据参数必须为NULL,因为不允许初始化这些类型的资源。
154431682218

资源视图请求

与1D纹理资源一样,2D纹理资源可以与所有四种资源视图类型一起使用,并且可以指定要由资源视图导出的资源的子集。2D纹理提供了各种各样的资源创建选项,并且还具有相应的大量资源视图配置。请仔细检查以下每种可能性。

Texture2D着色器资源视图。对于非阵列、非多重采样的2D纹理资源,着色器资源视图可以从资源中选择一系列mip贴图级别。这基本上与我们在1D纹理资源中看到的选择机制相同,只是每个mip贴图级别都是2D子源,而不是1D。这是在D3D11_SHADER_RESOURCE_VIEW_DESC中的D3D11_TEX2D_SRV结构中指定的,如清单2.30所示。

struct D3D11_TEX2D_SRV {
UINT MostDetailedMip;
UINT MipLevels;
}

起始mip映射级别在MostDetailedMip参数中指定,要使用的最大mip映射级数在MipLevels参数中指定。
154629761274
图2.34展示了在标准2D纹理资源中选择的一些示例资源区域。

2D纹理数组资源也以与1D资源相同的方式选择其范围。也就是说,它们选择一系列mip贴图级别以及数组元素范围。这是在D3D11_SHADER_RESOURCE_VIEW_DESC结构中的D3D11_TEX2D_ARRAY_RV结构中指定的,如清单2.31所示

struct D3D11_TEX2D_ARRAY_SRV {
UINT MostDetailedMip;
UINT MipLevels;
UINT FirstArraySlice;
UINT ArraySize;
}

在MostDetailedMip和MipLevel参数中选择mip贴图级别范围,如上所示。此外,数组元素范围是使用FirstArraySlicean和ArraySize参数选择的。一些示例范围如图2.35所示
154813842824
多采样2D纹理资源也可以与着色器资源视图一起使用。由于模拟采样的纹理不包含mip贴图,因此没有标准资源的子范围可供选择。这反映在D3D11_TEX2DMS_SRV结构中,因为它缺少参数。然而,多采样2D纹理阵列资源确实允许选择纹理阵列的元素的子范围。这是通过D3D11_SHADER_RESOURCE_VIEW_DESC结构中的D3D11_TEX2DMS_ARAY_SRV结构完成的,如清单2.32所示

struct D3D11_TEX2DMS_SRV {
UINT UnusedField_NothingToDefine;
}
struct D3D11_TEX2DMS_ARRAY_SRV {
UINT FirstArraySlice;
UINT ArraySize;
}

如前所述,数组范围是使用FirstArraySlice和ArraySize参数选择的。此范围选择的几个示例如图2.36所示。

当使用D3D11_RES0URCE_MISC_TEXTURECUBE杂项标志创建2D纹理阵列资源时,它们还有两个额外的特殊用途。这些阴影源视图可用于提供对六个阵列元素的立方体映射访问,其中每个元素表示立方体映射的一个面。对于单个多维数据集贴图着色器资源视图,将使用D3D11_TEXCUBE_SRV结构。在这种情况下,纹理阵列资源必须有六个元素,并且可以指定每个面的mip贴图级别的子范围。如清单2.33所示。

struct D3D11_TEXCUBE_SRV {
UINT MostDetailedMip;
UINT MipLevels;
}

154913261811

对于要在着色器资源视图中指定的立方体贴图阵列,将使用D3D11_TEXCUBE_ARRAY_SRV结构。此结构的成员允许选择要使用的mip映射级别范围,类似于单个立方体映射版本。但是,它们也允许指定要使用的第一个纹理数组元素,然后指定通过着色器资源视图可见的立方体贴图的数量。立方体映射的数量乘以六(表示立方体上的面的数量),以确定需要多少数组元素。如清单2.34所示。图2.37中显示了几个资源分区示例。

struct D3D11_TEXCUBE_ARRAY_SRV {
UINT MostDetailedMip;
UINT MipLevels;
UINT First2DArrayFace;
UINT NumCubes;
}

Texture2D无序访问视图

无序访问视图也可以用于将2D纹理资源绑定到管道。可以使用两种不同的子资源配置,它们遵循与1D纹理资源相同的范围选择范式。基于非阵列的2D纹理资源只能指定一个mip贴图级别以暴露于无序访问视图。这是使用D3D11_UN0RDERED_ACCESS_VIEW_DESC结构中的D3D11_TEX2D_UAV结构执行的,如清单2.35所示

typedef struct D3D11_TEX2D_UAV {
  UINT MipSlice;
} D3D11_TEX2D_UAV;

155056476463

mip贴图级别是使用MipSlice成员选择的。与阴影资源视图子资源的不同之处在于,只允许使用单个mip映射级别。如图2.38所示。
基于阵列的2D纹理资源也能够暴露于具有无序访问视图的可编程着色器程序。这允许在数组元素的子范围上指定单个mip映射级别。这些选择是使用D3D11_UN0RDERED_ACCESS_VIEW_DESC结构中的3D11_TEX2D_ARRAY_AV结构进行的,如清单2.36所示

typedef struct D3D11_TEX2D_ARRAY_UAV {
  UINT MipSlice;
  UINT FirstArraySlice;
  UINT ArraySize;
} D3D11_TEX2D_ARRAY_UAV;

155153124727
155200788854

数组范围选择以熟悉的方式执行,FirstArraySlice标记范围的开始,Ar-raySize指定要使用的数量。为了澄清,该子资源选择如图2.39所示

Texture2D渲染目标视图

正如我们在“使用2D纹理”部分中所看到的,2D纹理的主要用途之一是作为渲染目标。根据创建纹理资源的选项,允许将这些资源与渲染目标视图一起使用四种不同的配置。没有多重采样或阵列元素的标准2D纹理可以指定要与渲染目标视图一起显示的单个mip贴图级别。这是通过D3D11_RENDER_TARGET_VIEW_DESC结构中的D3D11_TEX2D_RTV结构完成的,如清单2.37所示

typedef struct D3D11_TEX2D_RTV {
  UINT MipSlice;
} D3D11_TEX2D_RTV;

2D纹理阵列资源提供与无序访问视图相同类型的子资源选项,允许在纹理阵列元素内的可选择范围内指定单个mip贴图级别。这是通过D3D11_RENDER_TARGET_VIEW_DESC结构中的D3D11_TEX2D_ARRAY_RTV结构完成的,如清单2.38所示。

typedef struct D3D11_TEX2D_ARRAY_RTV {
  UINT MipSlice;
  UINT FirstArraySlice;
  UINT ArraySize;
} D3D11_TEX2D_ARRAY_RTV;

多采样2D纹理资源的主要职责是接收渲染操作的结果作为渲染目标。渲染目标视图是将这些资源附加到管道的主要方式。对于资源的非数组版本和数组版本,子资源选择结构如清单2.39所示。

struct D3D11_TEX2DMS_RTV {
UINT UnusedField_NothingToDefine;
}

typedef struct D3D11_TEX2DMS_ARRAY_RTV {
  UINT FirstArraySlice;
  UINT ArraySize;
} D3D11_TEX2DMS_ARRAY_RTV;

清单2.39中可以看到,对于标准的2D多采样纹理资源,不可能有子资源选择。但是,2D多采样纹理阵列允许选择阵列元素的子范围。这些选择如图2.40所示。

2D纹理深度模版视图

深度模具视图提供与渲染目标视图相同的选项,使渲染目标和深度模具目标匹配视图相对简单。清单2.40中提供了用于创建资源视图的各个结构以供参考。
155641169107

Struct D3D11_TEX2D_DSV {
UINT MipSlice ;
}
Struct D3D11_TEX2D_ARRAY_DSV {
UINT MipSlice;
UINT FirstArraySlice;
UINT ArraySize;
}
Struct D3D11_TEX2DMS_DSV {
UINT UnusedField_NothingToDefine;
}
struct D3D11_TEX2DMS_ARRAY_DSV {
UINT FirstArraySlice;
UINT ArraySize;
}

HLSL对象

正如我们在1D纹理资源案例中所看到的,可以通过声明适当的资源对象来与HLSL中的纹理资源交互。然后,此资源对象必须与着色器资源视图或附加了适当资源的无序访问视图相匹配。使用着色器资源视图时,资源对象仅允许对资源内容进行读取访问。这反映在可以声明用于着色器资源视图的资源对象类型中。下面只列出了资源类型。

  • Texture2D
  • Texture2DArray
  • Texture2DMS
  • Texture2DMSArray
  • TextureCube
  • TextureCubeArray

当然,这些资源中的每一个都指定了可以绑定到的特定类型的着色器资源视图。例如,Texture2DMS HLSL资源对象必须绑定到连接到多采样2D纹理资源的着色器资源查看。无序访问视图提供对附加资源的读写访问,但它只能与上面为着色器资源视图显示的资源对象的子集一起使用。可用的资源对象如下所示。

  • RWTexture2D
  • RWTexture2DArray

正如您所看到的,只有标准的2D纹理资源及其基于阵列的counterpart才能用于无序访问视图。这就忽略了多采样资源和立方体贴图纹理,尽管后者的资源仍然可以被操纵,就像RWTexture2DArray一样。清单2.41中显示了每个资源对象的示例HLSL声明。

Texture2D<float> tex01;
Texture2DArray<int3> tex02;
Texture2DMS<float4, 4> tex03;
Texture2DMS<float2, 16> tex04;
TextureCube<float3> tex05;
TextureCubeArray<float> tex06;
RWTexture2D<uint3> tex07;
RWTexture2DArray<float3> tex08;

从这些声明中可以看出,多采样纹理资源对象指定其格式,还可以选择指定资源中使用的子采样数。此样本计数过去在Direct3D10中是必需的,但自Direct3D10.1以来,计数规范已成为可选的。现在可以通过HLSL GetDimensions()方法查询样本数量,从而不需要直接指定。这样可以确保任何访问子样本的方法只尝试使用适当数量的样本。围绕这些资源对象中每一个的使用的语义将在第6章中进行更详细的介绍。

0 篇笔记 写笔记

作者信息
站长漫谈
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!