## 15.8. Image Sample Operations

### 15.8.1. Wrapping Operation

`Cube` images ignore the wrap modes specified in the sampler. Instead, if `VK_FILTER_NEAREST` is used within a miplevel then `VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE` is used, and if `VK_FILTER_LINEAR` is used within a miplevel then sampling at the edges is performed as described earlier in the Cube map edge handling section.

The first integer texel coordinate i is transformed based on the `addressModeU` parameter of the sampler.

\begin{align*} i &= \begin{cases} i \operatorname{mod} size & \textrm{for repeat} \\ (size-1) - \operatorname{mirror}((i \operatorname{mod} (2 \times size)) - size) & \textrm{for mirrored repeat} \\ \operatorname{clamp}(i,0,size-1) & \textrm{for clamp to edge} \\ \operatorname{clamp}(i,-1,size) & \textrm{for clamp to border} \\ \operatorname{clamp}(\operatorname{mirror}(i),0,size-1) & \textrm{for mirror clamp to edge} \end{cases} \end{align*}

where:

\begin{align*} &\operatorname{mirror}(n) = \begin{cases} n & \textrm{for }n \geq 0 \\ -(1+n) &\textrm{otherwise} \\ \end{cases} \end{align*}

$j$ (for 2D and Cube image) and $k$ (for 3D image) are similarly transformed based on the `addressModeV` and `addressModeW` parameters of the sampler, respectively.

### 15.8.2. Texel Gathering

SPIR-V instructions with `Gather` in the name return a vector derived from a 2x2 rectangular region of texels in the base level of the image view. The rules for the `VK_FILTER_LINEAR` minification filter are applied to identify the four selected texels. Each texel is then converted to an RGBA value according to conversion to RGBA and then swizzled. A four-component vector is then assembled by taking the component indicated by the `Component` value in the instruction from the swizzled color value of the four texels:

\begin{align*} \tau[R] &= \tau_{i0j1}[level_{base}][comp] \\ \tau[G] &= \tau_{i1j1}[level_{base}][comp] \\ \tau[B] &= \tau_{i1j0}[level_{base}][comp] \\ \tau[A] &= \tau_{i0j0}[level_{base}][comp] \end{align*}

where:

\begin{align*} \tau[level_{base}][comp] &= \begin{cases} \tau[level_{base}][R], &\textrm{for } comp = 0 \\ \tau[level_{base}][G], &\textrm{for } comp = 1 \\ \tau[level_{base}][B], &\textrm{for } comp = 2 \\ \tau[level_{base}][A], &\textrm{for } comp = 3 \end{cases}\\ comp &\textrm{ from SPIR-V operand Component} \end{align*}

### 15.8.3. Texel Filtering

If $\lambda$ is less than or equal to zero, the texture is said to be magnified, and the filter mode within a mip level is selected by the `magFilter` in the sampler. If $\lambda$ is greater than zero, the texture is said to be minified, and the filter mode within a mip level is selected by the `minFilter` in the sampler.

Within a miplevel, `VK_FILTER_NEAREST` filtering selects a single value using the $(i,j,k)$ texel coordinates, with all texels taken from layer l.

\begin{align*} \tau[level] &= \begin{cases} \tau_{ijk}[level], &\textrm{for 3D image} \\ \tau_{ij}[level], &\textrm{for 2D or Cube image} \\ \tau_{i}[level], &\textrm{for 1D image} \end{cases} \end{align*}

Within a miplevel, `VK_FILTER_LINEAR` filtering computes a weighted average of 8 (for 3D), 4 (for 2D or Cube), or 2 (for 1D) texel values, using the weights computed earlier:

\begin{align*} \tau_{3D}[level] & = (1-\alpha)(1-\beta)(1-\gamma)\tau_{i0j0k0}[level] \\ & \, + (\alpha)(1-\beta)(1-\gamma)\tau_{i1j0k0}[level] \\ & \, + (1-\alpha)(\beta)(1-\gamma)\tau_{i0j1k0}[level] \\ & \, + (\alpha)(\beta)(1-\gamma)\tau_{i1j1k0}[level] \\ & \, + (1-\alpha)(1-\beta)(\gamma)\tau_{i0j0k1}[level] \\ & \, + (\alpha)(1-\beta)(\gamma)\tau_{i1j0k1}[level] \\ & \, + (1-\alpha)(\beta)(\gamma)\tau_{i0j1k1}[level] \\ & \, + (\alpha)(\beta)(\gamma)\tau_{i1j1k1}[level] \end{align*}
\begin{align*} \tau_{2D}[level] & = (1-\alpha)(1-\beta)\tau_{i0j0}[level] \\ & \, + (\alpha)(1-\beta)\tau_{i1j0}[level] \\ & \, + (1-\alpha)(\beta)\tau_{i0j1}[level] \\ & \, + (\alpha)(\beta)\tau_{i1j1}[level] \end{align*}
\begin{align*} \tau_{1D}[level] & = (1-\alpha)\tau_{i0}[level] \\ & \, + (\alpha)\tau_{i1}[level] \end{align*}
\begin{align*} \tau[level] &= \begin{cases} \tau_{3D}[level], &\textrm{for 3D image} \\ \tau_{2D}[level], &\textrm{for 2D or Cube image} \\ \tau_{1D}[level], &\textrm{for 1D image} \end{cases} \end{align*}

Finally, mipmap filtering either selects a value from one miplevel or computes a weighted average between neighboring miplevels:

\begin{align*} \tau &= \begin{cases} \tau[d], &\textrm{for mipmode BASE or NEAREST} \\ (1-\delta)\tau[d_{hi}]+\delta\tau[d_{lo}], &\textrm{for mipmode LINEAR} \end{cases} \end{align*}

### 15.8.4. Texel Anisotropic Filtering

Anisotropic filtering is enabled by the `anisotropyEnable` in the sampler. When enabled, the image filtering scheme accounts for a degree of anisotropy.

The particular scheme for anisotropic texture filtering is implementation dependent. Implementations should consider the `magFilter`, `minFilter` and `mipmapMode` of the sampler to control the specifics of the anisotropic filtering scheme used. In addition, implementations should consider `minLod` and `maxLod` of the sampler.

The following describes one particular approach to implementing anisotropic filtering for the 2D Image case, implementations may choose other methods:

Given a `magFilter`, `minFilter` of `VK_FILTER_LINEAR` and a `mipmapMode` of `VK_SAMPLER_MIPMAP_MODE_NEAREST`:

Instead of a single isotropic sample, N isotropic samples are be sampled within the image footprint of the image level $d$ to approximate an anisotropic filter. The sum $\tau_{2Daniso}$ is defined using the single isotropic $\tau_{2D}$ (u,v) at level $d$ .

\begin{align*} \tau_{2Daniso} & = \frac{1}{N}\sum_{i=1}^{N} {\tau_{2D}\left ( u \left ( x - \frac{1}{2} + \frac{i}{N+1} , y \right ), \left ( v \left (x-\frac{1}{2}+\frac{i}{N+1} \right ), y \right ) \right )}, &\textrm{when } \rho_{x} > \rho_{y} \\ \tau_{2Daniso} &= \frac{1}{N}\sum_{i=1}^{N} {\tau_{2D}\left ( u \left ( x, y - \frac{1}{2} + \frac{i}{N+1} \right ), \left ( v \left (x,y-\frac{1}{2}+\frac{i}{N+1} \right ) \right ) \right )}, &\textrm{when } \rho_{y} \geq \rho_{x} \end{align*}

| editing-note
(Bill) EXT_texture_filter_anisotropic has not been updated since 2000, except for ES extension number (2007) and a minor speeling (sic) correction (2014), neither of which are functional changes. It is showing its age. In particular, there is an open issue about 3D textures. There are no interactions with ARB_texture_cube_map (approved 1999, promoted to core OpenGL 1.3 in 2001), let alone interactions with ARB_seamless_cube_map (approved and promoted to core OpenGL 3.2 in 2009). There are no interactions with texture offsets or texture gather.