GLSL: sampler1D vs sampler2D with Height of One

Sampling from a sampler1D versus a sampler2D with a height of one in GLSL primarily differs in coordinate dimensionality, filtering behavior, mipmap generation, and cross-platform compatibility. While both approaches can represent an identical one-dimensional array of texels in memory, sampler1D operates strictly along a single axis, whereas a 1xN sampler2D introduces a second axis that requires explicit coordinate management, alters hardware derivative calculations, and ensures broader compatibility across graphics APIs.

Coordinate Dimensionality and Syntax

The most immediate difference is the texture coordinate parameter required by the GLSL sampling functions:

  • sampler1D: Requires a scalar coordinate float (e.g., texture(tex1D, u)).
  • sampler2D: Requires a two-component vector vec2 (e.g., texture(tex2D, vec2(u, 0.5))).

When querying a 2D texture of size \(N \times 1\), you must supply a fixed V (or Y) coordinate. To sample the center of the single row of pixels, this value is typically set to 0.5. Passing an incorrect V coordinate can introduce sampling artifacts depending on the texture's wrapping modes.

Filtering and Edge Clamping

Texture filtering behaves differently across the unused dimension:

  • 1D Textures: Filtering (linear interpolation) only occurs along the X axis between adjacent texels. There is no concept of a perpendicular axis.
  • 2D Textures (\(N \times 1\)): Bilinear filtering considers both the X and Y axes. If the V coordinate shifts slightly away from 0.5 due to floating-point imprecision or custom calculations, the sampler will attempt to interpolate along the Y axis. If the texture wrapping mode is set to GL_REPEAT or GL_CLAMP_TO_BORDER, the sampled color might blend with the wrap target or border color instead of retaining the exact texel color. To prevent this, the texture's vertical wrap mode must explicitly be set to GL_CLAMP_TO_EDGE.

Derivatives and Mipmapping

Automatic Level of Detail (LOD) calculations rely on screen-space derivatives:

  • Derivatives: For sampler1D, the GPU calculates screen-space derivatives \(\frac{\partial u}{\partial x}\) and \(\frac{\partial u}{\partial y}\) exclusively on the 1D coordinate. For sampler2D, derivatives are computed for both coordinates (\(\frac{\partial u}{\partial x}\), \(\frac{\partial u}{\partial y}\), \(\frac{\partial v}{\partial x}\), and \(\frac{\partial v}{\partial y}\)).
  • Mipmaps: In a true 1D texture, mipmap levels divide the width by two at each step until reaching \(1 \times 1\). For an \(N \times 1\) 2D texture, the mip chain reduces the width while the height remains clamped at \(1\) (\(N \times 1, \frac{N}{2} \times 1, \dots, 1 \times 1\)). While the resulting mip chain structure is identical, the 2D sampler's LOD selection can theoretically be skewed if the V coordinate varies across fragments.

Hardware Execution and Performance

On modern desktop GPUs, dedicated 1D texture hardware is rare. Most drivers allocate 1D textures as 2D textures internally with a height of one or as an array layer. Consequently, memory bandwidth, cache hit rates, and execution speed are virtually identical between the two on desktop platforms. However, sampler2D incurs a negligible overhead of passing and interpolating a 64-bit coordinate pair (vec2) rather than a single 32-bit float (float).

Platform Compatibility

The choice between the two often comes down to API support:

  • OpenGL Desktop: Fully supports sampler1D across all core and compatibility profiles.
  • OpenGL ES and WebGL: Do not support 1D textures or sampler1D. In mobile, embedded, and web environments, an \(N \times 1\) texture bound to a sampler2D is the standard and necessary approach for 1D data lookup tables.