Tex::MipMode::Trilinear vs Aniso: Understanding OpenImageIO Texture Filtering Modes
In OpenImageIO, Tex::MipMode::Trilinear performs isotropic filtering by blending two mip levels with equal weighting in all directions, while Tex::MipMode::Aniso applies anisotropic filtering that adapts sample distribution to the elongated shape of the texel footprint, providing higher quality for oblique viewing angles at the cost of additional texture samples.
The Tex::MipMode enum in the Academy Software Foundation's OpenImageIO library defines how the texture system samples mip-mapped images. Located in src/include/OpenImageIO/texture.h at lines 108-113, this enum includes both Trilinear and Aniso modes for developers who need to balance rendering quality against performance. Understanding the distinction between these filtering strategies is essential for optimizing texture lookups in production rendering pipelines.
MipMode Enum Definition
According to the source code in src/include/OpenImageIO/texture.h, the MipMode enum defines the available mip-mapping strategies:
enum class MipMode : uint8_t {
Default, ///< Default high-quality lookup (same as Aniso)
NoMIP, ///< Use only the highest-resolution image
OneLevel, ///< Use a single mip level
Trilinear, ///< Use two mip levels and linearly blend between them
Aniso ///< Use two mip levels with anisotropic filtering
};
Both Trilinear and Aniso select two adjacent mip-map levels and interpolate between them. The critical distinction lies in how the texel footprint is filtered within those levels.
Key Differences Between Trilinear and Aniso
Filtering Direction and Footprint Handling
Trilinear applies isotropic filtering, meaning the same filter size is applied equally in both u and v directions. This creates a uniform sampling pattern regardless of the texture's orientation on screen.
Aniso implements anisotropic filtering that adapts to the shape of the projected texel footprint. When a surface is viewed at a grazing angle, the texture footprint becomes elongated. The Aniso mode detects this elongation and applies a longer filter along the dominant axis while maintaining tighter sampling across the narrow axis.
Visual Quality and Sampling Characteristics
Trilinear provides good quality for surfaces facing the camera directly or with moderate texture slopes. However, it may produce visible blur or aliasing when textures are viewed at steep angles or contain high-frequency detail, as the isotropic filter cannot distinguish between the stretched and compressed directions of the footprint.
Aniso delivers higher quality for oblique views or stretched textures by taking more samples along the elongated direction. This reduces blur and aliasing on surfaces like ground planes, hair, or architectural elements viewed at grazing angles. The default anisotropic ratio is set to 32, though this can be configured via TextureOpt::anisotropic.
Performance Characteristics
Trilinear is faster because it samples a fixed 2×2 (or 4×4 depending on batch width) set of texels per mip level. The predictable memory access pattern and constant sample count make it ideal for performance-critical applications like UI thumbnails or distant geometry.
Aniso incurs additional overhead because the number of samples scales with the anisotropic ratio and the aspect ratio of the footprint. According to the implementation in src/libtexture/texturesys.cpp at lines 3397-3401, the sample count is determined by round_to_multiple_of_pow2(2 * options.anisotropic, 4). This leads to more texel fetches and increased computation, though the visual improvement often justifies the cost for primary surfaces.
Implementation Details in OpenImageIO
The architectural distinction between these modes is implemented in src/libtexture/texturesys.cpp. While Aniso internally calls the same sampling engine as Trilinear, it adds an anisotropic weighting step that modifies how samples are distributed across the footprint.
The function anisotropic_aspect computes the stretch of the texture footprint, determining how elongated the sampling pattern should be. This calculation directly influences the number of samples taken along the major axis, ensuring that high-frequency detail is preserved even when the texture is stretched across many pixels.
Practical Code Examples
C++ Texture System Usage
When using the OpenImageIO C++ API, you configure the mip mode through the TextureOpt structure before calling the texture lookup:
#include <OpenImageIO/texture.h>
using namespace OIIO;
void demo_trilinear(TextureSystem* ts, const std::string& filename)
{
TextureOpt opt;
opt.mipmode = Tex::MipMode::Trilinear; // two-level linear blend
// optional: set filter width, wrap mode, etc.
float result[3];
bool ok = ts->texture(filename, /*s*/0.5f, /*t*/0.5f,
result, 3, TypeDesc::FLOAT, opt);
// result now holds the filtered RGB values
}
void demo_aniso(TextureSystem* ts, const std::string& filename)
{
TextureOpt opt;
opt.mipmode = Tex::MipMode::Aniso; // anisotropic filtering
opt.anisotropic = 16; // request up to 16× anisotropy
float result[3];
bool ok = ts->texture(filename, /*s*/0.5f, /*t*/0.5f,
result, 3, TypeDesc::FLOAT, opt);
// Higher-quality result for steep viewing angles
}
Python API Usage
The Python bindings expose the same functionality through the TextureOpt class:
import OpenImageIO as oiio
ts = oiio.TextureSystem()
opt = oiio.TextureOpt()
opt.mipmode = "Trilinear" # or "Aniso"
opt.anisotropic = 8 # only matters for Aniso mode
pixel = ts.texture("myTex.exr", 0.5, 0.5, opt)
print("Filtered color:", pixel)
Summary
- Tex::MipMode::Trilinear provides fast, isotropic filtering by blending two mip levels with uniform sampling in all directions, ideal for UI elements and distant geometry where performance is critical.
- Tex::MipMode::Aniso delivers higher visual fidelity through anisotropic filtering that adapts to elongated texel footprints, making it essential for ground planes, hair, and architectural surfaces viewed at grazing angles.
- Both modes are defined in
src/include/OpenImageIO/texture.hand implemented insrc/libtexture/texturesys.cpp, with Aniso using theanisotropic_aspectfunction to determine sample distribution based on theanisotropicoption (default 32). - Aniso incurs higher computational cost because the number of samples scales with the anisotropic ratio using the formula
round_to_multiple_of_pow2(2 * options.anisotropic, 4).
Frequently Asked Questions
When should I use Trilinear instead of Aniso?
Use Trilinear when rendering distant geometry, UI thumbnails, or any surface where the texture is viewed roughly face-on and performance is a higher priority than marginal quality gains. Trilinear requires fewer texture samples per lookup, making it faster for scenes with heavy overdraw or limited memory bandwidth.
How does the anisotropic ratio affect rendering quality?
The anisotropic ratio (controlled via TextureOpt::anisotropic) determines the maximum elongation factor the filter will handle. Higher values allow the sampler to take more samples along stretched footprints, reducing blur on surfaces viewed at extreme grazing angles. The default value of 32 provides high quality for most production scenarios, though values up to 16 or 64 are common depending on the renderer's performance constraints.
Can I change the mip mode at runtime?
Yes, the mip mode is specified per texture lookup through the TextureOpt structure passed to TextureSystem::texture(). This allows different objects or materials in the same scene to use different filtering strategies. For example, background elements might use Trilinear while foreground hero assets use Aniso, optimizing the trade-off between quality and performance on a per-lookup basis.
Where is the anisotropic filtering logic implemented?
The anisotropic filtering calculations are implemented in src/libtexture/texturesys.cpp around lines 3397-3401. This code calls the anisotropic_aspect function to compute the footprint stretch and determines the sample count using round_to_multiple_of_pow2(2 * options.anisotropic, 4). The actual texel fetching reuses the same infrastructure as trilinear filtering but distributes samples anisotropically based on these calculations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →