# Wrap Modes in OpenImageIO TextureSystem: Complete Guide to Texture Coordinate Handling

> Explore OpenImageIO TextureSystem's eight wrap modes for texture coordinate handling. Understand how Black, Clamp, Periodic, and Mirror modes affect sampling and texture lookups.

- Repository: [Academy Software Foundation/openimageio](https://github.com/academysoftwarefoundation/openimageio)
- Tags: deep-dive
- Published: 2026-02-23

---

**OpenImageIO's TextureSystem provides eight distinct wrap modes—including Black, Clamp, Periodic, and Mirror—that determine how texture coordinates outside the [0,1] range are handled during sampling, with each mode dispatched through the `wrap_functions` lookup table in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp).**

The AcademySoftwareFoundation/openimageio library powers high-performance texture sampling for VFX and animation pipelines. Understanding the available **wrap modes in TextureSystem** is essential for controlling edge behavior when UV coordinates extend beyond the standard texture domain, preventing artifacts in production renders.

## What Are Wrap Modes in TextureSystem?

Texture coordinates in computer graphics frequently fall outside the canonical [0, 1] range. The **wrap mode** defines how the **TextureSystem** handles these out-of-bounds coordinates during lookup operations. In OpenImageIO, this behavior is controlled through the `Tex::Wrap` enum defined in [`src/include/OpenImageIO/texture.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/texture.h) (lines 80-91).

When performing a texture lookup, the system stores the chosen wrap mode in a `TextureOpt` object via the `swrap`, `twrap`, and `rwrap` members for each respective dimension. The `TextureSystemImpl` then selects the appropriate handling function from the `wrap_functions` table defined in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) (lines 580-595).

## Available Wrap Modes in OpenImageIO

The `Tex::Wrap` enum provides eight distinct behaviors for handling out-of-range texture coordinates.

### Default

The `Default` wrap mode delegates to the texture file's own wrap setting stored in metadata. If the image file does not specify a wrap mode, the system falls back to `Black`. This allows artists to embed wrap preferences directly into texture assets.

### Black

When using `Black`, any texture coordinate outside [0, 1] returns a black (zero) pixel value. According to the implementation in [`src/libOpenImageIO/imageio.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libOpenImageIO/imageio.cpp) (line 1345), the `wrap_black` function marks such samples as *invalid* while leaving the coordinate unchanged. This mode is essential for debugging UV errors in production renders.

### Clamp

The `Clamp` mode restricts coordinates to the nearest edge texel. Values less than 0 become 0, while values greater than 1 become 1. This creates a "smear" effect where the edge pixel repeats indefinitely, commonly used to prevent black artifacts on texture borders.

### Periodic

`Periodic` enables infinite tiling by applying a modulo operation (`coord % 1`) to texture coordinates. This creates seamless repeating patterns across surfaces. The implementation automatically optimizes for power-of-two textures when possible.

### Mirror

The `Mirror` mode creates a back-and-forth tiling pattern where every other repetition is flipped horizontally or vertically. This produces seamless textures without visible seams at tile boundaries, ideal for symmetric patterns and procedural textures.

### PeriodicPow2

This mode functions identically to `Periodic` but uses fast bit-masking operations when texture dimensions are powers of two. As noted in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) (lines 1608-1610), the constructor automatically upgrades `Periodic` to `PeriodicPow2` when detecting appropriate dimensions, providing significant performance improvements for real-time rendering and game textures.

### PeriodicSharedBorder

Designed specifically for environment maps, `PeriodicSharedBorder` behaves like `Periodic` but shares the outermost texel column and row with the opposite side. This eliminates filtering seams at the wrap boundary when using cube maps or lat-long environment textures.

## How Wrap Modes Impact Texture Lookups

The wrap mode selection directly influences the sampling algorithm's execution path. When `texture()` or `texture3d()` is called, the system consults the `wrap_functions` lookup table in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) to dispatch the appropriate coordinate transformation.

For `Black` mode, the `wrap_black` function in [`src/libOpenImageIO/imageio.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libOpenImageIO/imageio.cpp) immediately returns invalid sample flags without coordinate transformation overhead. Conversely, `Clamp` invokes boundary checks that constrain coordinates to valid texel indices. The `Periodic` family of modes performs modular arithmetic, with `PeriodicPow2` utilizing bitwise operations for hardware-friendly optimization.

These implementations affect both performance and visual output. `PeriodicPow2` reduces CPU cycles for power-of-two textures, while `Mirror` requires additional conditional logic to determine reflection direction. The `TextureOpt` structure stores these preferences per-direction, allowing asymmetric wrapping (e.g., `Periodic` in U, `Clamp` in V) for specialized projection mapping.

## Configuring Wrap Modes in Production Code

Implementing wrap modes requires setting the appropriate enum values on `TextureOpt` objects before sampling.

### C++ Implementation

In C++, include the texture header and configure the `TextureOpt` structure:

```cpp
#include <OpenImageIO/texture.h>
using namespace OIIO;

// Create texture system and options
TextureSystem *ts = TextureSystem::create();
TextureOpt opt;

// Configure asymmetric wrapping: tile horizontally, clamp vertically
opt.swrap = Tex::Wrap::Periodic;  // Repeat in U direction
opt.twrap = Tex::Wrap::Clamp;     // Hold edge in V direction

// Perform lookup with out-of-range coordinates
float result[4];
bool success = ts->texture("texture.tx", opt, 1.5f, -0.2f,
                          0.0f, 0.0f, 0.0f, 0.0f,
                          4, result);

```

### Python API Usage

The Python bindings provide identical functionality through the `OpenImageIO` module:

```python
import OpenImageIO as oiio

# Initialize texture system

tex = oiio.TextureSystem()
opt = oiio.TextureOpt()

# Set mirror wrap for seamless symmetric tiling

opt.swrap = oiio.Wrap.Mirror
opt.twrap = oiio.Wrap.Mirror

# Sample with coordinates outside [0,1] range

result = tex.texture("pattern.tx", opt, 2.3, 0.8, 0, 0, 0, 0, 4)
print(f"Sampled value: {result}")

```

### Runtime Inspection

Verify effective wrap modes using system attributes:

```python

# Query current wrap settings

print(f"S-wrap mode: {tex.getattribute('swrap')}")
print(f"T-wrap mode: {tex.getattribute('twrap')}")

```

## Performance and Optimization Considerations

Selecting appropriate wrap modes impacts rendering performance significantly. The `PeriodicPow2` mode provides substantial optimizations for power-of-two textures by replacing division operations with bitwise masking, as implemented in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) (lines 1608-1610). The system automatically promotes `Periodic` to `PeriodicPow2` when texture dimensions meet the power-of-two requirement.

`Black` mode offers the fastest failure path for invalid coordinates, immediately returning zero values without coordinate transformation overhead. Conversely, `Mirror` requires additional conditional branching to determine reflection direction, potentially impacting vectorized SIMD operations.

For production environments, prefer `PeriodicPow2` for tiling textures when possible, and use `Black` for debugging UV errors. The `PeriodicSharedBorder` mode incurs minimal overhead compared to standard `Periodic` while eliminating environment map seams.

## Summary

- OpenImageIO's **TextureSystem** provides eight distinct **wrap modes** defined in [`src/include/OpenImageIO/texture.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/texture.h) to handle out-of-bounds texture coordinates.
- **Black** returns zero values for invalid coordinates, while **Clamp** restricts coordinates to edge texels and **Periodic** enables infinite tiling through modular arithmetic.
- **Mirror** creates seamless back-and-forth patterns, **PeriodicPow2** optimizes tiling for power-of-two textures via bit-masking, and **PeriodicSharedBorder** eliminates seams in environment maps.
- Wrap modes are configured per-direction through the `TextureOpt` structure and dispatched via the `wrap_functions` table in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp).

## Frequently Asked Questions

### What is the default wrap mode in OpenImageIO TextureSystem?

The **Default** wrap mode delegates to the texture file's embedded metadata. If the image file does not specify a wrap mode, the system automatically falls back to **Black**, returning zero values for any out-of-bounds coordinates and marking the sample as invalid.

### How does PeriodicPow2 differ from standard Periodic wrap mode?

**PeriodicPow2** functions identically to **Periodic** but replaces expensive modulo operations with fast bit-masking when texture dimensions are powers of two. According to [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) (lines 1608-1610), the system automatically upgrades **Periodic** to **PeriodicPow2** for eligible textures, providing significant performance improvements in real-time rendering.

### Can I use different wrap modes for U and V coordinates?

Yes, OpenImageIO supports **asymmetric wrapping** through independent configuration of `swrap` (U direction), `twrap` (V direction), and `rwrap` (W direction for 3D textures) in the `TextureOpt` structure. This allows combinations such as **Periodic** tiling horizontally with **Clamp** edge-holding vertically for specialized projection mapping.

### Which wrap mode should I use for environment maps to avoid seams?

For environment maps and spherical projections, use **PeriodicSharedBorder**. This mode behaves like standard **Periodic** tiling but shares the outermost texel column and row with the opposite side, eliminating filtering seams at the wrap boundary that commonly appear in cube maps and lat-long environment textures.