Texture Atlas Management
Relevant source files
The following files were used as context for generating this wiki page:
Texture Atlas Management in HoloPrint is the system responsible for consolidating individual Minecraft block textures into a single optimized image. This process is critical for generating Bedrock Edition resource packs and rendering 3D previews efficiently. By stitching multiple textures into one "atlas," the application reduces the number of texture binds required by the GPU, optimizing performance for holograms containing hundreds of unique blocks.
The system handles complex Minecraft-specific logic, including blocks.json remapping, TGA to PNG conversion, foliage/water tinting, and the generation of varying opacity levels for in-game controls. It interfaces directly with the geometry generation logic to resolve UV coordinates for every block face in a structure.
Architecture and Data Flow
The texture management lifecycle begins when HoloPrint.js orchestrates the conversion process. It utilizes the BlockGeoMaker to identify all required texture references, which are then passed to the TextureAtlas class for processing.
The flow ensures that every unique texture fragment (defined by its path, tint, and opacity) is processed once and placed optimally within the atlas.
Sources: src/HoloPrint.js:203-210, src/TextureAtlas.js:63-125
Key Components
TextureAtlas Class
The core engine residing in src/TextureAtlas.js. It maintains the state of the atlas, including mapping data, flipbook texture sizes, and the final image blobs.
- Constructor: Initializes with configurations, resource pack stacks, and mapping JSONs. Sources: src/TextureAtlas.js:46-61
- makeAtlas(textureRefs): The primary entry point that transforms a list of
TextureReferenceobjects into a stitched atlas. Sources: src/TextureAtlas.js:66-125 - #stitchTextureAtlas(imageFragments): Uses the
potpacklibrary to calculate the most space-efficient layout for the textures. Sources: src/TextureAtlas.js:264-325
Mapping and Configuration
The system relies on external JSON data to handle inconsistencies in Minecraft's naming conventions and rendering rules.
| Property | Description | Source |
|---|---|---|
blocks_dot_json_patches | Maps inconsistent block IDs (e.g., grass_block to grass). | src/data/textureAtlasMappings.json:3-9 |
blocks_to_use_carried_textures | Identifies blocks that should use "carried" versions for better visual accuracy. | src/data/textureAtlasMappings.json:10 |
transparent_blocks | Defines default opacity for specific blocks (e.g., Water at 0.65). | src/data/textureAtlasMappings.json:11-15 |
terrain_texture_tints | Defines hex codes for foliage and water tints. | src/data/textureAtlasMappings.json:16-46 |
Logic and Processing
1. Texture Identification and Path Resolution
For every block face, the system must determine the correct image path. This involves checking blocks.json for texture keys and then cross-referencing terrain_texture.json to find the actual file path.
Sources: src/TextureAtlas.js:127-186
2. Image Processing
The system handles multiple image formats and modifications:
- TGA Support: Uses
TGALoaderto process.tgafiles, which are common in Minecraft Bedrock. Sources: src/TextureAtlas.js:215-227 - Tinting: Applies foliage and water tints to grayscale textures. TGA images require specific logic where only full-opacity pixels are tinted. Sources: src/TextureAtlas.js:425-442
- Cropping: Automatically crops empty space from textures to maximize atlas efficiency. Sources: src/TextureAtlas.js:241-255
3. Stitching and Packing Efficiency
Stitching uses the potpack algorithm. The system attempts multiple packing strategies (with and without width presorting) to find the highest "fill efficiency."
Sources: src/TextureAtlas.js:284-290
Sources: src/TextureAtlas.js:264-315
4. Post-Processing: Outlines and Opacity
To make hologram blocks easier to distinguish, the system can add outlines and generate multiple opacity variants.
- Texture Outlines: Adds a border around every texture fragment in the atlas based on
TEXTURE_OUTLINE_WIDTH. Sources: src/TextureAtlas.js:352-404 - Opacity Variants: If
MULTIPLE_OPACITIESis enabled, the system generates several versions of the atlas ranging from 40% to 100% opacity. Sources: src/TextureAtlas.js:317-323
Interaction with Geometry
Once the atlas is generated, the resulting UV coordinates must be mapped back to the 3D geometry. This is handled by BlockGeoMaker.resolveTemplateFaceUvs.
// src/BlockGeoMaker.js:774-785
static resolveTemplateFaceUvs(faces, textureAtlas) {
return faces.map(face => {
let imageUv = textureAtlas.uvs[face["textureRefI"]];
// ... sorting and cropping logic ...
return {
"normal": face["normal"],
"transparency": imageUv["transparency"],
"vertices": vertices.map(vertex => ({
"pos": vertex["pos"],
"uv": tuple([
+((imageUv["uv"][0] + imageUv["uv_size"][0] * (vertex["corner"] & 1)) / textureAtlas.textureWidth).toFixed(4),
+(1 - (imageUv["uv"][1] + imageUv["uv_size"][1] * (vertex["corner"] >> 1)) / textureAtlas.textureHeight).toFixed(4)
])
}))
};
});
}
Sources: src/BlockGeoMaker.js:770-791
The PreviewRenderer later uses the transparency value calculated during atlas generation to determine if a block requires the MeshLambertMaterial with transparent: true.
Sources: src/PreviewRenderer.js:347-360
Summary
The Texture Atlas Management system acts as a bridge between Minecraft's fragmented asset structure and a high-performance rendering pipeline. By centralizing texture resolution, image processing, and packing logic into the TextureAtlas class, HoloPrint ensures that holograms are visually accurate to the game while maintaining the performance required for web-based 3D previews and mobile-friendly resource packs.