GL_TEXTURE_2D_ARRAY, eliminating texture binding overhead during rendering.
TextureManager Class
Defined insrc/renderer/texture_manager.h:
Initialization
Create a texture manager with fixed dimensions:GL_TEXTURE_2D_ARRAY with:
- Width: 16 pixels
- Height: 16 pixels
- Depth: 256 layers (one per texture)
- Format:
GL_RGBAwithGL_UNSIGNED_BYTE - Mipmapping: Controlled by
Options::MIPMAP_TYPE
src/renderer/texture_manager.cpp:8-22 for initialization details.
Texture Loading
Adding Textures
stbi_set_flip_vertically_on_load(true)) to match OpenGL’s bottom-left origin.
Texture Indices
Textures are assigned sequential indices based on load order:Deduplication
Attempting to add the same texture multiple times is safe - it will only be loaded once:src/renderer/texture_manager.cpp:31-50 for the loading implementation.
Texture Array Binding
Critical Invariant
The texture array MUST be bound before anyglTexSubImage3D or glGenerateMipmap calls.
To prevent accidentally uploading block textures into the shadow map (which is also a GL_TEXTURE_2D_ARRAY), TextureManager explicitly binds its texture array in:
-
Constructor (before
glTexImage3D) -
generate_mipmaps() (before
glGenerateMipmap) -
add_texture() (before
glTexSubImage3D)
Rendering Setup
During rendering, bind the texture array to texture unit 0:src/world.cpp:634-635 for the main rendering setup.
Texture Filtering and Mipmaps
Filter Modes
Configured viaOptions::MIPMAP_TYPE in src/options.h:
GL_NEAREST- No mipmaps, nearest neighborGL_LINEAR- No mipmaps, bilinear filteringGL_NEAREST_MIPMAP_NEAREST- Mipmaps, nearest neighborGL_NEAREST_MIPMAP_LINEAR- Mipmaps, trilinear filtering (default)GL_LINEAR_MIPMAP_LINEAR- Mipmaps, fully linear
GL_NEAREST for pixel-perfect textures at close range.
Mipmap Generation
Mipmaps are generated after all textures are loaded:Texture Format
File Format
All textures must be PNG files inassets/textures/:
Dimensions
All textures must match the dimensions specified in theTextureManager constructor (typically 16×16).
Mismatched dimensions: Textures with different sizes may still load but will be stretched/compressed to fit the atlas dimensions, causing visual artifacts.
Color Channels
Textures are loaded as RGBA:- RGB channels: Color data
- Alpha channel: Transparency (used for alpha testing in shaders)
Block Texture Assignment
Block types reference textures by name indata/blocks.mccpp:
TextureManager::get_texture_index() when loading block definitions.
Debugging
Pure Black Blocks
Symptom: All blocks render as solid black. Cause: Texture array is not bound correctly during rendering. Fix:- Ensure
glBindTexture(GL_TEXTURE_2D_ARRAY, tm.texture_array)is called before drawing - Verify
u_TextureArraySampleruniform is set to 0 - Check that
GL_TEXTURE0is active
Magenta/Pink Blocks
Symptom: Blocks render as diagnostic magenta color. Cause: Texture index is invalid or texture failed to load. Fix:- Check console for “Failed load tex:” messages
- Verify PNG files exist in
assets/textures/ - Check file permissions
Texture Appears in Wrong Layer
Symptom: Wrong texture shows on blocks. Cause: Shadow map was bound whenadd_texture() was called, uploading block textures into the wrong array.
Fix: Ensure TextureManager methods always bind texture_array before GL calls (already implemented in current version).
See AGENTS.md:41-49 for details on this bug and fix.
Performance Considerations
Single Texture Array
Using a texture array eliminates texture binding overhead:- No
glBindTexturecalls between draw calls - All chunks can be rendered with the same GL state
- GPU can batch draw calls more efficiently
Atlas Size
The maximum number of textures (256 by default) is a hard limit:- Cannot add more textures than
max_texturesspecified at construction - Exceeding this limit will cause GL errors
- Increase if you need more unique textures (e.g., 512)
Memory Usage
Texture array memory =width × height × depth × 4 bytes × (1 + mipmap levels)
For 16×16×256 with mipmaps:
- Base level: 16 × 16 × 256 × 4 = 256 KB
- Mipmaps: ~85 KB additional
- Total: ~341 KB (negligible on modern GPUs)
Related Pages
- Rendering Overview - Texture usage in rendering pipeline
- Shader System - Sampling textures in shaders
- Shadow Mapping - Shadow map texture array interaction