What Is the Difference Between sampler2D and sampler2DArray?
In GLSL, sampler2D is used to access a single,
standalone two-dimensional texture using standard normalized
coordinates, while sampler2DArray accesses a
two-dimensional texture array containing multiple layers of identical
size and format using a three-component coordinate. Texture arrays allow
shaders to select from multiple 2D texture layers within a single draw
call without the texture binding overhead, edge bleeding, or mipmapping
artifacts typical of traditional texture atlases.
Fundamental Architectural Differences
A sampler2D uniform represents a single 2D texture
object (GL_TEXTURE_2D). It is sampled using two-dimensional
texture coordinates \((u, v)\),
returning a color value interpolated across the width and height of that
individual image.
A sampler2DArray uniform represents a 2D texture array
(GL_TEXTURE_2D_ARRAY). It consists of an ordered sequence
of discrete 2D image layers. All layers in the array must share the
exact same dimensions, internal pixel format, and mipmap level count.
Sampling requires a three-component vector \((u, v, layer)\), where the third coordinate
specifies the zero-based layer index.
Sampling and Filtering Behavior
While sampler2DArray uses a vec3
coordinate, it is fundamentally different from a 3D volume texture
(sampler3D):
- No Cross-Layer Filtering: Hardware texture filtering (linear or nearest) occurs strictly within the selected 2D layer across the \(u\) and \(v\) axes. The GPU rounds the layer index to the nearest integer layer and does not interpolate between adjacent layers in the array.
- Independent Mipmapping: Mipmaps are generated per layer. When minification occurs, filtering samples from the mip levels belonging exclusively to the specified layer.
- Standard 2D Sampling: A standard
sampler2Dperforms bilinear or trilinear filtering across the \(u\) and \(v\) dimensions of its single image and its corresponding mipmaps.
GLSL Usage and Syntax Comparison
Sampling each type in GLSL requires different coordinate dimensions and sampler uniforms.
Standard 2D Texture
(sampler2D)
#version 330 core
uniform sampler2D u_Texture;
in vec2 v_TexCoord;
out vec4 FragColor;
void main()
{
// Samples a single 2D texture using standard UV coordinates
FragColor = texture(u_Texture, v_TexCoord);
}2D Texture Array
(sampler2DArray)
#version 330 core
uniform sampler2DArray u_TextureArray;
in vec2 v_TexCoord;
flat in int v_LayerIndex;
out vec4 FragColor;
void main()
{
// Samples a specific layer using a vec3(u, v, layerIndex)
vec3 arrayCoord = vec3(v_TexCoord, float(v_LayerIndex));
FragColor = texture(u_TextureArray, arrayCoord);
}Performance and Use Cases
Understanding when to choose sampler2DArray over
sampler2D depends on rendering architecture and batching
requirements.
| Feature | sampler2D |
sampler2DArray |
|---|---|---|
| OpenGL Target | GL_TEXTURE_2D |
GL_TEXTURE_2D_ARRAY |
| Coordinate Type | vec2(u, v) |
vec3(u, v, layer) |
| Batching Efficiency | Requires rebinding or atlasing | High; draws many textures in one call |
| Bleeding Artifacts | Atlas seams require UV clamping/padding | None; layer boundaries are hardware-isolated |
| Dimension Constraints | Any supported dimension | All layers must share identical dimensions |
Benefits of Texture Arrays Over Texture Atlases
Texture arrays are commonly used in terrain splatting, UI rendering,
particle systems, and voxel engines to render multiple distinct surfaces
in a single draw call. Unlike texture atlases—which pack multiple images
into one giant 2D texture—texture arrays do not suffer from sub-texture
coordinate bleeding or mipmap filtering artifacts at borders, and
wrapping modes like GL_REPEAT function independently on
every layer.