Version: 2021.3
3D 纹理
立方体贴图

纹理数组

纹理数组是具有相同大小/格式/标记的 2D 纹理的集合,这些纹理对于 GPU 而言像是单个对象,并可在着色器中使用纹理元素索引进行采样。它们可以用于实现自定义地形渲染系统或其他特殊效果,让您高效访问大量相同大小和格式的纹理。2D 纹理数组的元素也称为切片或图层。

平台支持

纹理数组需要受到底层图形 API 和 GPU 的支持。纹理数组在以下平台上可用:

  • Direct3D 11/12(Windows、Xbox One)
  • OpenGL Core(Mac OS X、Linux)
  • Metal(iOS、Mac OS X)
  • OpenGL ES 3.0(Android、WebGL 2.0)

其他平台(OpenGL ES 2.0 或 WebGL 1.0)不支持纹理数组。可使用 SystemInfo.supports2DArrayTextures 在运行时确定纹理数组支持情况。

导入纹理数组

可以从划分成单元格的源纹理文件导入纹理数组。这些被称为翻页纹理。为此需要执行以下操作:

  1. 将源纹理导入您的 Unity 项目。
  2. 在您的项目视图中,选择生成的纹理资源。Unity 将在 Inspector 中显示纹理导入设置。
  3. 在 Inspector 中,将 Texture Shape 设置为 2D Array。Unity 显示 Columns 和 Rows 属性。
  4. ColumnsRows 设置为适用于翻页纹理的值。
  5. 单击 Apply

有关更多信息,请参阅纹理导入设置

使用脚本创建和填充纹理数组

从 C# 脚本创建纹理数组,使用 Texture2DArray 类来初始化纹理和设置像素数据,并使用 AssetDatabase.CreateAsset 将对象保存为资源文件。

通常,纹理数组完全是在 GPU 内存中使用,但您可以使用 Graphics.CopyTextureTexture2DArray.GetPixelsTexture2DArray.SetPixels 与系统内存之间双向传输像素。

将纹理数组用作渲染目标

纹理数组元素也可用作渲染目标。使用 RenderTexture.dimension 提前指定渲染目标是否是 2D 纹理数组。Graphics.SetRenderTargetdepthSlice 参数可指定要渲染到的 Mipmap 级别或立方体贴图面。在支持“分层渲染”(例如,几何着色器)的平台上,可将 depthSlice 参数设置为 –1 以便将整个纹理数组设置为渲染目标。此外还可使用几何着色器来渲染到个别元素中。

在着色器中使用纹理数组

由于纹理数组并非适用于所有平台,因此着色器需要使用适当的编译目标或功能要求来访问纹理数组。支持纹理数组的最低着色器模型编译目标为 3.5,功能名称为 2darray

使用以下可声明和采样纹理数组:

  • UNITY_DECLARE_TEX2DARRAY(name) 在 HLSL 代码中声明纹理数组采样器变量。
  • UNITY_SAMPLE_TEX2DARRAY(name,uv) 使用 float3 UV 采样纹理数组;坐标的 z 分量是数组元素索引。
  • UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) 使用显式 Mipmap 级别采样纹理数组。

示例

以下着色器示例通过使用对象空间顶点位置作为坐标来采样纹理数组:

Shader "Example/Sample2DArrayTexture"
{
    Properties
    {
        _MyArr ("Tex", 2DArray) = "" {}
        _SliceRange ("Slices", Range(0,16)) = 6
        _UVScale ("UVScale", Float) = 1.0
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 纹理数组并非在任何地方都可用,
            // 只能在它们所在的平台上编译着色器
            #pragma require 2darray
            
            #include "UnityCG.cginc"

            struct v2f
            {
                float3 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _SliceRange;
            float _UVScale;

            v2f vert (float4 vertex : POSITION)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, vertex);
                o.uv.xy = (vertex.xy + 0.5) * _UVScale;
                o.uv.z = (vertex.z + 0.5) * _SliceRange;
                return o;
            }
            
            UNITY_DECLARE_TEX2DARRAY(_MyArr);

            half4 frag (v2f i) : SV_Target
            {
                return UNITY_SAMPLE_TEX2DARRAY(_MyArr, i.uv);
            }
            ENDCG
        }
    }
}

另请参阅

3D 纹理
立方体贴图