类似于常规 2D 纹理(Texture2D 类,着色器中的 sampler2D__)、立方体贴图(Cubemap 类,着色器中的 samplerCUBE__)和 3D 纹理(Texture3D 类,着色器中的 __sampler3D__),Unity 也支持 2D 纹理数组。
纹理数组是具有相同大小/格式/标记的 2D 纹理的集合,这些纹理对于 GPU 而言像是单个对象,并可在着色器中使用纹理元素索引进行采样。它们可以用于实现自定义地形渲染系统或其他特殊效果,让您高效访问大量相同大小和格式的纹理。2D 纹理数组的元素也称为切片或图层。
纹理数组需要受到底层图形 API 和 GPU 的支持。纹理数组在以下平台上可用:
其他平台(OpenGL ES 2.0 或 WebGL 1.0)不支持纹理数组。可使用 SystemInfo.supports2DArrayTextures 在运行时确定纹理数组支持情况。
由于纹理数组没有纹理导入管线,必须在脚本中创建纹理数组。可使用 Texture2DArray 类来创建和填充纹理数组。请注意,纹理数组可序列化为资源,因此可以借助 Editor 脚本中的数据创建和填充纹理数组。
通常,纹理数组完全是在 GPU 内存中使用,但您可以使用 Graphics.CopyTexture、Texture2DArray.GetPixels 和 Texture2DArray.SetPixels 与系统内存之间双向传输像素。
纹理数组元素也可用作渲染目标。使用 RenderTexture.dimension 提前指定渲染目标是否是 2D 纹理数组。Graphics.SetRenderTarget 的 depthSlice 参数可指定要渲染到的 Mipmap 级别或立方体贴图面。在支持“分层渲染”(例如,几何着色器)的平台上,可将 depthSlice 参数设置为 –1 以便将整个纹理数组设置为渲染目标。此外还可使用几何着色器来渲染到个别元素中。
由于纹理数组并非适用于所有平台,因此着色器需要使用适当的编译目标或功能要求来访问纹理数组。支持纹理数组的最低着色器模型编译目标为 3.5
,功能名称为 2darray
。
使用以下宏可声明和采样纹理数组:
以下着色器示例通过使用对象空间顶点位置作为坐标来采样纹理数组:
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
}
}
}