How maketx Generates Efficient MIP-Mapped Textures for Renderers

The maketx tool generates efficient MIP-mapped textures by converting source images into tiled, multi-resolution pyramid files using parallelized filtering, intelligent memory management, and atomic file writes, all orchestrated through the ImageBufAlgo::make_texture function in OpenImageIO.

The maketx command-line utility is the standard tool in the OpenImageIO (OIIO) ecosystem for preparing production-ready texture assets. It transforms arbitrary image formats into the .tx format—tiled, MIP-mapped textures optimized for renderer consumption. At its core, the tool delegates all texture generation logic to ImageBufAlgo::make_texture, implemented in src/libOpenImageIO/maketexture.cpp.

Architecture of the maketx Pipeline

Command-Line Interface and Configuration

The entry point resides in src/maketx/maketx.cpp, where the getargs function parses command-line flags into an ImageSpec object. This specification carries critical parameters including tile dimensions, filter kernels, sharpening values, and threading counts.

Core Texture Generation Engine

The actual processing happens in ImageBufAlgo::make_texture within src/libOpenImageIO/maketexture.cpp. This function implements an eight-stage pipeline that handles everything from memory allocation to final file output.

The MIP-Map Generation Process

Input Reading and Memory Strategy

When processing begins, maketx creates an ImageBuf from the source. If the image is smaller than the 1 GB read-local threshold, it loads entirely into RAM; otherwise, it streams data on demand via ImageCache. This logic appears in maketexture.cpp around lines 37-41, allowing the tool to handle both small assets and massive production plates without exhausting system memory.

Preprocessing Optimizations

Before MIP generation, the tool applies several data-reduction strategies to minimize final file size. These include light-probe conversion, bump-map to slope-map transformation, Gaussian CDF table generation, constant-color detection, alpha-channel dropping, and channel renaming. These steps, located in the pre-process block of maketexture.cpp (lines 58-124), can dramatically reduce data volume before the computationally expensive filtering operations begin.

Tiled Layout and MIP Chain Construction

The output ImageSpec is forced to a tiled layout with default dimensions of 64×64 pixels, though users can specify alternatives via --tile. Tiling is mandatory for efficient random-access sampling by renderers. The MIP chain is constructed by repeatedly down-sampling each level using the selected filter—options include box, lanczos, mitchell, and others—with optional sharpening (--sharpen) applied during reduction to preserve detail.

Parallel Execution

All computationally intensive loops leverage OIIO::parallel_image and ImageBufAlgo::parallel_image, respecting the user-specified thread count via -t or --threads. This parallel dispatch, visible in maketexture.cpp around lines 124-132, ensures multi-core CPUs are fully utilized during filtering, statistical analysis, and histogram generation.

Atomic File Output

To prevent renderers from encountering partially-written textures, maketx writes to a uniquely-named temporary file in the target directory. Only upon successful completion does it rename the file to the final .tx extension. This safety mechanism appears in maketexture.cpp lines 56-63, ensuring that a renderer never reads a corrupted texture missing MIP levels.

Metadata Embedding

The final output includes comprehensive metadata: all processing options, the original command line (stored in the Software attribute), and any generated lookup tables such as Gaussian CDF data. Renderers retrieve these attributes for correct texture reconstruction and to verify processing parameters.

Practical Usage Examples

Command-Line Usage

The most common workflow uses the maketx binary with explicit control over threading, tile size, and filter quality:


# Generate a tiled, MIP-mapped texture with 128-pixel tiles,

# Lanczos filtering, sharpening, and 8 threads

maketx -t 8 --tile 128 128 --filter lanczos3 \
       --sharpen 0.5 -v input.exr -o output.tx
  • -t 8 utilizes eight threads for parallel processing.
  • --tile 128 128 increases tile dimensions for better cache locality in specific renderers.
  • --filter lanczos3 selects a higher-quality reconstruction filter for the MIP chain.

C++ API Integration

For pipeline integration, invoke the same functionality programmatically via ImageBufAlgo::make_texture:

#include <OpenImageIO/imagebufalgo.h>
using namespace OIIO;

// Configure texture generation parameters
ImageSpec config;
config.attribute("maketx:threads", 8);
config.attribute("maketx:tile_width", 128);
config.attribute("maketx:tile_height", 128);
config.attribute("maketx:filtername", "lanczos3");
config.attribute("maketx:sharpen", 0.5f);

// Execute texture creation
bool ok = ImageBufAlgo::make_texture(
            ImageBufAlgo::MakeTxTexture,  // Standard texture mode
            "input.exr",                  // Source image path
            "output.tx",                  // Destination path
            config,                       // Configuration spec
            &std::cout);                  // Optional progress output

The maketx:* attributes mirror the command-line flags, allowing complete control over the MIP-generation pipeline from within custom applications.

Summary

  • maketx converts arbitrary images into tiled, MIP-mapped textures via ImageBufAlgo::make_texture in src/libOpenImageIO/maketexture.cpp.
  • The tool employs intelligent memory management using a 1 GB threshold to choose between full RAM loading and streaming via ImageCache.
  • Parallel filtering using OIIO::parallel_image maximizes CPU utilization during MIP generation.
  • Atomic file writes (temporary file then rename) ensure renderers never encounter partially written textures.
  • Default 64×64 tiling and configurable filters (box, lanczos, mitchell) optimize for renderer random-access patterns.

Frequently Asked Questions

What is the default tile size for maketx textures?

The default tile size is 64×64 pixels, which provides an optimal balance between I/O efficiency and memory locality for most renderers. You can override this using the --tile flag or the maketx:tile_width and maketx:tile_height attributes when using the C++ API. Larger tiles (e.g., 128×128) may improve cache performance for specific rendering engines.

Which filters does maketx support for MIP-map generation?

maketx supports multiple reconstruction filters for down-sampling, including box, lanczos, mitchell, triangle, and catmull-rom. The default filter is box for maximum speed, but lanczos or mitchell provide higher quality for production assets. You can specify the filter using --filter or maketx:filtername, and apply sharpening with --sharpen to preserve detail during reduction.

How does maketx handle large images that exceed available RAM?

When processing images larger than the 1 GB read-local threshold, maketx switches from loading the entire image into RAM to streaming data on demand via the ImageCache subsystem. This threshold check occurs in src/libOpenImageIO/maketexture.cpp (lines 37-41). This streaming approach allows maketx to process arbitrarily large production plates without exhausting system memory, though it may trade some speed for memory efficiency.

Why does maketx write to a temporary file before renaming?

To prevent renderers from reading corrupted or incomplete textures, maketx implements an atomic write strategy. It first writes the entire texture—including all MIP levels and metadata—to a uniquely-named temporary file in the destination directory. Only after the write completes successfully does it rename the file to the final .tx extension. This logic in src/libOpenImageIO/maketexture.cpp (lines 56-63) ensures that a renderer never encounters a partially written MIP level, which could cause crashes or rendering artifacts.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →