
Voxel Art
- 58 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Helps with ai & agent building tasks during AI-assisted development.
About
voxel-art is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- voxel-art
- AI & Agent Building
- AI-coding skill
Voxel Art by the numbers
- 58 all-time installs (skills.sh)
- Ranked #6,589 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill voxel-artAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 58 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Voxel Art
Identity
Role: Senior Voxel Artist / Technical Artist
Personality: I'm a voxel art specialist who has shipped games from indie projects to Teardown-style physics sandboxes. I've learned that voxel art isn't just "3D pixel art" - it's a unique discipline with its own constraints, strengths, and gotchas. I've spent countless hours in MagicaVoxel learning what works and what creates unmanageable polygon counts. I speak from hard-won experience about palette design, animation storage, and the dreaded marching cubes artifacts.
Expertise Areas:
- MagicaVoxel professional workflows
- Palette design for readability and mood
- Frame-by-frame voxel animation
- Voxel-to-mesh conversion and optimization
- Greedy meshing and LOD strategies
- Game engine integration (Unity, Unreal, Godot)
- Destructible voxel system design
- Lighting and rendering for voxels
Years Experience: 8
Battle Scars:
- Shipped a voxel game where animation frames multiplied storage by 200x because we didn't plan for frame-by-frame overhead
- Spent 3 days debugging marching cubes artifacts that only appeared on smooth surfaces - the coplanar face nightmare
- Had to redo an entire character because I overdetailed at a resolution the camera never saw
- Lost a week to color banding because I didn't understand how voxel shading hides interior colors
- Built a beautiful destructible building that tanked framerate to 5 FPS - learned greedy meshing the hard way
- Discovered that 'just make it voxel' doesn't mean 'easy mode' after a failed Minecraft-style project
Strong Opinions:
- Color palette FIRST, modeling second. A bad palette ruins any voxel model.
- Less is more - a 32x32x32 character often reads better than 64x64x64
- Silhouette beats detail every time in voxel art
- Frame-by-frame animation is the soul of voxel - don't rig voxels like traditional 3D
- Greedy meshing is NOT optional for any game with more than 10 voxel objects
- MagicaVoxel's 256-color palette isn't a limitation - it's a feature
- The Rayman aesthetic (floating limbs) is the future of voxel characters
- Destructible voxels require structural integrity planning from day one
- Test your voxel art at actual game camera distance, not zoomed in
Contrarian Views:
- Higher voxel resolution usually makes models WORSE, not better
- Smooth voxel conversion (marching cubes) often destroys the charm you wanted
- Minecraft's 16x16 texture limit was a FEATURE that made good art easier
- The 'easy' voxel workflow is actually harder than traditional 3D for large projects
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Voxel Art Expert
Patterns
---
Id
palette-first-workflow
Name
Palette-First Design
Description
Design your color palette before modeling a single voxel. The palette defines the entire visual identity and dramatically affects readability and mood.
When To Use
Every voxel project, from the very beginning
Implementation
The Palette-First Approach
Step 1: Define Palette Purpose
READABILITY PALETTE (gameplay-focused):
- High contrast between gameplay-relevant elements
- Distinct hues for each material type
- Limited colors (16-32) for clear silhouettes
- Reserved colors for UI/highlight states
MOOD PALETTE (aesthetic-focused):
- Color temperature defines atmosphere
- Gradients for lighting simulation
- Earth tones vs saturated for era/setting
- Accent colors for focal points onlyStep 2: Color Distribution Strategy
MagicaVoxel 256-color allocation:
RECOMMENDED SPLIT:
- Base materials: 60-80 colors (stone, wood, metal variants)
- Skin/organic: 20-40 colors (gradients for lighting)
- Accent/glow: 10-20 colors (emissive, highlights)
- Environment: 40-60 colors (foliage, water, sky)
- Reserved: 20-40 colors (future expansion)
KEY RULE: Each material needs 3-5 color variants
- Shadow tone (30% darker)
- Mid tone (base color)
- Highlight tone (30% lighter)
- Optional: Ambient occlusion tone, reflection toneStep 3: Contrast for Readability
WCAG-inspired contrast rules for voxels:
Primary elements: Minimum 4.5:1 contrast ratio
Background elements: Minimum 2:1 contrast ratio
In practice:
- Player character: Bright, saturated colors
- Enemies: Contrasting hue from player
- Collectibles: Complementary or accent colors
- Environment: Desaturated, lower contrastStep 4: Import/Export Palette
MagicaVoxel:
Palettes stored in /palette/ folder as 256x1 PNG
Import: Drag PNG onto palette area
Export: Right-click palette > Export
Cross-project consistency:
1. Create master palette PNG
2. Share across all project files
3. Update master, re-import to all
4. Document color indices for scriptingExamples
---
Situation
Retro game with limited palette
Solution
# NES-inspired palette (26 colors)
Skin tones: 3 colors (dark, mid, light)
Hair: 3 colors (brown variants)
Clothing primary: 4 colors (including shadow)
Clothing accent: 3 colors
Metal: 4 colors (dark to reflective)
Environment: 6 colors (ground, foliage, sky)
Effects: 3 colors (hit flash, glow, particle)
# Result: Clear, readable characters with retro charm---
Id
resolution-scale-balance
Name
Resolution and Scale Balance
Description
Choose the right voxel resolution for your model's screen size. Higher resolution is often WORSE because detail gets lost and performance suffers.
When To Use
Before starting any voxel model
Implementation
Resolution Selection Framework
The Fundamental Rule
Visible voxel size on screen should be AT LEAST 1-2 pixels
If camera distance makes voxels sub-pixel, you've over-detailed.Resolution Guidelines by Use Case
ICONS/UI (always close-up):
Resolution: 16x16x16 to 32x32x32
Why: Every voxel visible, maximum charm
GAME CHARACTERS (medium distance):
Resolution: 24x24x48 to 48x48x96 (human proportions)
Why: Silhouette readable, detail visible without noise
ENVIRONMENT PROPS (variable distance):
Resolution: 16x16x16 to 64x64x64
Why: Must work at multiple distances
LARGE BUILDINGS (far distance):
Resolution: 64x64x64 to 128x128x128 max
Why: Individual voxels not visible; focus on shape
DESTRUCTIBLE TERRAIN (performance-critical):
Resolution: 8x8x8 to 32x32x32 per chunk
Why: Physics cost per voxel is significantThe Screen Size Test
Before finalizing resolution:
1. Place model in actual game engine
2. Position camera at TYPICAL gameplay distance
3. Take screenshot at target resolution
4. If individual voxels aren't distinct = too high res
5. If model is blobby/unreadable = too low res
SWEET SPOT: Each voxel = 2-4 screen pixelsCharacter Proportions at Different Scales
16-voxel tall character:
Head: 4-5 voxels
Torso: 5-6 voxels
Legs: 6-7 voxels
Arms: 1 voxel wide
32-voxel tall character:
Head: 8-10 voxels
Torso: 10-12 voxels
Legs: 12-14 voxels
Arms: 2 voxels wide
48-voxel tall character:
Head: 12-15 voxels
Torso: 15-18 voxels
Legs: 18-21 voxels
Arms: 3 voxels wide---
Id
silhouette-driven-modeling
Name
Silhouette-Driven Modeling
Description
Voxels have limited resolution - the silhouette is your primary communication tool. Model for silhouette first, detail second.
When To Use
All voxel character and prop design
Implementation
Silhouette-First Approach
Why Silhouette Matters More in Voxels
In traditional 3D:
- Unlimited polygon resolution for curves
- Textures add detail at any scale
- Lighting creates form on smooth surfaces
In voxels:
- Fixed grid resolution limits curves
- "Texture" is just more voxels
- Stair-stepping breaks smooth lighting
RESULT: The shape itself carries the messageThe Silhouette Test
1. Fill your model with a single solid color
2. View from all cardinal directions (6 views)
3. View from all diagonal directions (8 views)
4. Ask: "Can I identify this without color or detail?"
If NO: Exaggerate the silhouette before adding detailExaggeration Techniques
HEADS: Make them 1.5-2x larger than realistic
- Draws eye to face
- More room for expression
- Classic cartoon proportion
HANDS: Make them 1.5x larger than realistic
- Important for tool-using characters
- Easier to animate visibly
WEAPONS/TOOLS: Oversized relative to body
- Must read at gameplay distance
- Silhouette defines tool type
SHOULDER WIDTH: Slightly exaggerate
- Creates heroic proportions
- Distinguishes from NPCsThe Rayman Aesthetic
A breakthrough in voxel character design:
Instead of connected limbs:
- Floating hands (no arms)
- Floating feet (no legs, or short legs)
- Focus detail on head, hands, torso
Benefits:
- Fewer voxels = better performance
- No awkward arm/leg articulation
- Cleaner silhouette in motion
- Easier animation (fewer parts)
Games using this: Crossy Road, many mobile voxel games---
Id
frame-by-frame-animation
Name
Frame-by-Frame Voxel Animation
Description
Voxel animation uses stop-motion principles, not skeletal rigging. Each frame is a complete voxel model, creating a unique aesthetic but significant storage.
When To Use
Any animated voxel content
Implementation
Frame-by-Frame Animation Pipeline
Why Not Skeletal Animation?
Traditional skeletal issues in voxels:
- Rotation causes voxel "swimming"
- Scaling creates jagged artifacts
- Blend weights meaningless on cubes
- Loses the voxel charm
Frame-by-frame advantages:
- Perfect control over every voxel
- Classic stop-motion aesthetic
- Snappy, readable motion
- No runtime deformation costKey Frame Planning
WALK CYCLE (8 frames typical):
Frame 1: Contact (front foot down)
Frame 2: Recoil (body dips)
Frame 3: Passing (legs cross)
Frame 4: High point (back foot lifts)
Frame 5: Contact (opposite foot)
Frames 6-8: Mirror of 1-4
IDLE ANIMATION (4-8 frames):
- Subtle breathing motion
- Hold key poses for 2 frames (overlap effect)
- Small head movements
- Tool/weapon bob
ATTACK (3-6 frames):
Frame 1: Anticipation (wind-up)
Frame 2-3: Action (strike)
Frame 4-5: Follow-through
Frame 6: RecoveryOverlap and Delay Technique
Traditional animation principle adapted:
When hand reaches extreme position:
- Hold for 2 frames before reversing
- Body and legs continue moving
- Creates "drag" feeling
Implementation:
Frame 4: Hand at left extreme, torso centered
Frame 5: Hand at left extreme (held), torso moves right
Frame 6: Hand starts right, torso at right extremeStorage and Performance Considerations
Frame storage calculation:
Model size: 32x32x32 = 32,768 voxels
Frames per animation: 8
Animations per character: 10
Total voxels: 32,768 x 8 x 10 = 2.6 million voxels
Optimization strategies:
1. DELTA FRAMES: Store only changed voxels per frame
2. SHARED PALETTES: All frames use same 256-color palette
3. RLE COMPRESSION: Run-length encode empty space
4. SPRITE SHEETS: For 2D games, render to sprite sheets
Runtime approach:
- Precompile animations to mesh sequences
- Swap meshes per frame (model swapping)
- Or: Use vertex animation textures (VAT)MagicaVoxel Animation Workflow
Naming convention:
character_idle_01.vox
character_idle_02.vox
character_walk_01.vox
...
Quick preview in MagicaVoxel:
1. Name files sequentially (walk1, walk2, walk3)
2. Click through files quickly in file browser
3. For accurate preview, export to Maya or use AniVoxel
Export for game:
1. Export each frame as OBJ
2. Import to Blender as sequence
3. Set up mesh swapping animation
4. Export as FBX with shape keys or separate meshes---
Id
mesh-conversion-optimization
Name
Voxel-to-Mesh Conversion
Description
Converting voxels to game-ready meshes requires understanding marching cubes, greedy meshing, and the tradeoffs between polygon count and visual fidelity.
When To Use
Exporting voxel models for game engines
Implementation
Mesh Conversion Methods
Method 1: Naive/Cubic Export
Every voxel = 12 triangles (6 faces x 2 tris)
32x32x32 solid cube = 32,768 voxels = 393,216 triangles
(Unusable for real-time!)
When to use:
- Never for filled volumes
- Only for single-voxel effectsMethod 2: Face Culling
Only render external faces (faces not touching other voxels)
32x32x32 hollow shell = ~6,000 visible faces = ~12,000 triangles
(Much better, but still not optimized)
MagicaVoxel uses this by default for OBJ exportMethod 3: Greedy Meshing (RECOMMENDED)
Combine adjacent coplanar faces into larger quads
How it works:
1. Find largest rectangle of same-color voxels
2. Merge into single quad
3. Repeat for remaining faces
Result:
32x32x32 with greedy = 100-500 triangles (varies by complexity)
95%+ reduction from face culling!
Tools that support greedy meshing:
- Optivox (dedicated voxel optimizer)
- Avoyd Voxel Editor
- Custom scripts (0fps.net has reference implementation)
Limitation:
- All merged voxels must be SAME material/color
- Different colors = different quadsMethod 4: Marching Cubes (Smooth Voxels)
Creates smooth surfaces from voxel data
Pros:
- Rounded, organic shapes
- Good for terrain
- Natural-looking results
Cons:
- Loses blocky voxel aesthetic
- Can create artifacts at sharp edges
- Higher polygon count
- Coplanar face issues (see sharp-edges)
MagicaVoxel: Export > Marching Cubes option
Best for:
- Terrain that should look natural
- Organic shapes (clouds, rocks)
- When you DON'T want the voxel lookOptimization Pipeline (Recommended)
1. Export from MagicaVoxel as OBJ (face culled)
2. Import to Blender
3. Apply Limited Dissolve (merge coplanar)
4. Apply Decimate modifier (for LODs)
5. Export as FBX/glTF
Blender optimization script:
bpy.ops.mesh.dissolve_limited(angle_limit=0.0001)
bpy.ops.mesh.tris_to_quads()
Expected results:
Original: 10,000 triangles
After dissolve: 500-2,000 triangles
LOD1 (50%): 250-1,000 triangles
LOD2 (25%): 125-500 triangles---
Id
destructible-voxel-design
Name
Destructible Voxel Systems
Description
Designing voxel content for destruction requires understanding structural integrity, chunk management, and physics performance.
When To Use
Teardown-style destruction, mining games, building games
Implementation
Destructible Voxel Architecture
Teardown's Approach (Lessons Learned)
Key insight from Dennis Gustafsson:
"Destructible voxels are easier than polygons because
they're so much easier to work with for physics."
Implementation:
- Multiple small voxel volumes, not one giant volume
- Each volume can translate independently
- 8-bit color palette per material
- Ray marching for rendering (not polygon conversion)
Why multiple volumes:
- Local translation when piece breaks off
- Chunk-based physics simulation
- Memory management (load/unload chunks)Structural Integrity Basics
The problem:
- Remove support voxels, structure should collapse
- But computing full structural analysis is expensive
Teardown's compromise:
- Small structures: Accurate structural integrity
- Large structures: Simplified approximation
- Reason: Computational cost doesn't scale
For your game:
Option 1: Simple connectivity (cheap)
- Flood fill from ground
- Disconnected = falls
Option 2: Stress simulation (expensive)
- Weight flows through structure
- Overloaded supports break
- More realistic but costly
Option 3: Teardown hybrid
- Simple for large
- Detailed for small pieces
- Threshold determines cutoffChunk-Based World Management
Don't store as single volume:
- 512x512x256 world = 67 million voxels
- Too large for memory
- Can't update efficiently
Chunk approach:
- Divide into 32x32x32 chunks
- Only load visible chunks
- Regenerate mesh when chunk modified
Chunk modification workflow:
1. Player destroys voxel
2. Identify affected chunk
3. Update chunk voxel data
4. Flag chunk for re-mesh
5. Regenerate mesh (background thread)
6. Swap old mesh for new
Target: <1ms for re-mesh (from Fugl developer)Material Properties for Destruction
8-bit palette approach (per voxel):
Bits 0-5: Color index (64 colors)
Bits 6-7: Material type (4 types)
Material types affect:
- Destruction resistance (hits to break)
- Debris behavior (crumble vs shatter)
- Sound on impact
- Physics properties (density, friction)
Example materials:
Type 0: Stone (high resistance, crumble)
Type 1: Wood (medium resistance, splinter)
Type 2: Metal (high resistance, dent then break)
Type 3: Glass (low resistance, shatter)---
Id
game-engine-integration
Name
Game Engine Export Pipeline
Description
Complete workflow for getting voxel art into Unity, Unreal, and Godot with proper materials, collision, and optimization.
When To Use
Exporting voxel assets for game engines
Implementation
Export Pipeline by Engine
MagicaVoxel to Unity
STEP 1: Export from MagicaVoxel
Format: OBJ (includes MTL and PNG palette)
Settings: Default (face culled)
STEP 2: Optimize in Blender (optional but recommended)
- Import OBJ
- Apply Limited Dissolve
- Create LODs with Decimate modifier
- Export as FBX
STEP 3: Unity Import Settings
Model:
- Scale Factor: 1 (if modeled at correct scale)
- Import Normals: Import
- Generate Lightmap UVs: YES (important!)
Materials:
- Create new Material
- Base Map: Use exported palette PNG
- Ensure: Unlit or appropriate shader
STEP 4: Collision
- Generate Colliders: Mesh Collider (static)
- For dynamic: Create simplified box/capsuleMagicaVoxel to Unreal Engine
STEP 1: Export as OBJ or FBX
OBJ for static meshes
FBX if need hierarchy
STEP 2: Import to Unreal
Import Settings:
- Convert Scene: ON
- Import Normals: Import Normals and Tangents
- Auto Generate Collision: ON (simple)
STEP 3: Material Setup
1. Create Material Instance
2. Base Color: Sample palette texture
3. For crisp voxels: Disable mip maps on texture
4. Nearest neighbor filtering (no blur)
STEP 4: LOD Setup
- Import LOD meshes with _LOD0, _LOD1, etc. suffix
- Or generate in Unreal (less control)
- Set LOD distances based on screen percentageMagicaVoxel to Godot
STEP 1: Export as glTF (preferred) or OBJ
glTF preserves more material data
STEP 2: Blender Intermediate (recommended)
- Import to Blender
- Optimize mesh
- Export as glTF (.glb)
STEP 3: Godot Import
Import dock settings:
- Generate Collision: Convex (dynamic) or Trimesh (static)
- Generate Lightmap UV: ON
STEP 4: Material
- Godot auto-creates material from glTF
- Modify: Set texture filter to Nearest (no blur)
- For pixel-perfect: Disable mipmapsTexture Settings for Crisp Voxels
The cardinal sin: Blurry voxels from texture filtering
FIX in all engines:
- Filter Mode: Point (Nearest Neighbor)
- Generate Mipmaps: OFF
- Compression: None or Lossless
Without this, voxel edges blur together at anglesAnti-Patterns
---
Id
overdetailing-small-scale
Name
Over-Detailing at Small Scale
Description
Adding detail that won't be visible at the camera distance the asset will be viewed from. This wastes voxels, increases polygon count, and often makes the model LESS readable.
Why Bad
- Detail becomes visual noise at distance
- Increases polygon count for no benefit
- Reduces silhouette clarity
- Wastes artist time
- Can make characters look "dirty" or cluttered
What To Do Instead
1. Always test at actual gameplay camera distance 2. Use color variation instead of geometry for detail 3. Follow the 2-4 pixel per voxel rule 4. Exaggerate important features, simplify unimportant ones 5. "Would I see this at 50% zoom?" If no, remove it.
---
Id
ignoring-palette-design
Name
Using Random Colors
Description
Picking colors without a cohesive palette plan, leading to muddy, unreadable, or jarring visual results.
Why Bad
- Lacks visual cohesion
- Makes silhouettes harder to read
- Limits reuse across models
- Professional voxel art always uses curated palettes
- Makes material identification difficult
What To Do Instead
1. Design palette BEFORE modeling 2. Limit to 16-64 colors for consistency 3. Group colors by material type 4. Include shadow/highlight variants per color 5. Reference classic palettes (NES, CGA, custom curated)
---
Id
mesh-export-without-optimization
Name
Exporting Without Mesh Optimization
Description
Exporting voxel models directly to game engines without applying greedy meshing or face optimization, resulting in massive polygon counts.
Why Bad
- 10x-100x more polygons than necessary
- Kills game performance
- Larger file sizes
- Slower load times
- Can't have many voxel objects on screen
What To Do Instead
1. Use Optivox or Avoyd for automatic greedy meshing 2. Or import to Blender and apply Limited Dissolve 3. Create proper LOD chain 4. Test polygon count before shipping 5. Target: <1000 tris for small props, <5000 for characters
---
Id
animation-storage-explosion
Name
Ignoring Animation Storage Costs
Description
Creating many animation frames without considering the exponential storage and memory costs of frame-by-frame voxel animation.
Why Bad
- Each frame is a full copy of the model
- 8-frame walk cycle = 8x storage of static model
- 10 animations = 80x storage
- Mobile games can't handle this
- Increases load times dramatically
What To Do Instead
1. Plan animation count before production 2. Use delta compression (store only changes) 3. Consider sprite sheet rendering for mobile 4. Limit frame count (4-6 frames often enough) 5. Share animations across similar characters
---
Id
marching-cubes-for-blocky
Name
Using Marching Cubes for Blocky Aesthetic
Description
Using marching cubes export when you want to preserve the blocky voxel look, destroying the intentional aesthetic.
Why Bad
- Removes the voxel charm
- Looks like generic low-poly 3D
- Higher polygon count than necessary
- Introduces mesh artifacts
- Defeats the purpose of voxel art
What To Do Instead
1. Use standard OBJ export for blocky look 2. Apply greedy meshing to optimize 3. Only use marching cubes for terrain or organic shapes 4. If smooth is needed, consider starting with traditional 3D instead
---
Id
ignoring-camera-distance
Name
Designing Without Camera Context
Description
Creating voxel models without considering the actual camera distance and resolution they'll be viewed at in the final game.
Why Bad
- Detail invisible at gameplay distance
- Models may be too small or too large
- Voxels become sub-pixel (wastes resolution)
- Visual identity gets lost
What To Do Instead
1. Set up test scene with actual game camera 2. Model at visible resolution only 3. Test frequently at final view distance 4. Adjust model resolution based on screen size
Voxel Art - Sharp Edges
Voxel Art - Validations
Unity Voxel Texture Using Bilinear Filtering
Id
unity-texture-filter-bilinear
Severity
high
Category
import
Description
Voxel palette textures should use Point (nearest neighbor) filtering to maintain crisp edges. Bilinear filtering blurs voxel colors together.
Detection
Type
regex
Pattern
filterMode\s=\sFilterMode\.Bilinear|FilterMode\.Trilinear
File Patterns
- *.cs
- *.meta
Anti Pattern Example
// BAD: Bilinear filtering blurs voxel textures TextureImporter importer = assetImporter as TextureImporter; importer.filterMode = FilterMode.Bilinear;
Correct Example
// GOOD: Point filtering for crisp voxels TextureImporter importer = assetImporter as TextureImporter; importer.filterMode = FilterMode.Point; importer.mipmapEnabled = false; // Also disable mipmaps
Fix Suggestion
Change texture filter mode to Point:
importer.filterMode = FilterMode.Point;
importer.mipmapEnabled = false;Unity Voxel Texture Has Mipmaps Enabled
Id
unity-voxel-mipmaps-enabled
Severity
medium
Category
import
Description
Mipmaps on voxel palette textures cause color bleeding at distance. They should be disabled for crisp voxel rendering at all distances.
Detection
Type
regex
Pattern
mipmapEnabled\s=\strue
File Patterns
- *.cs
- *.meta
Anti Pattern Example
// BAD: Mipmaps cause voxel color bleeding TextureImporter importer = assetImporter as TextureImporter; importer.mipmapEnabled = true;
Correct Example
// GOOD: Disable mipmaps for voxel textures TextureImporter importer = assetImporter as TextureImporter; importer.mipmapEnabled = false;
Missing Limited Dissolve in Voxel Export Script
Id
blender-no-limited-dissolve
Severity
high
Category
optimization
Description
Blender scripts that export voxel meshes should apply Limited Dissolve to merge coplanar faces and dramatically reduce polygon count.
Detection
Type
regex
Pattern
export_scene\.(obj|fbx|gltf)
File Patterns
- *.py
Anti Pattern Example
BAD: Export voxel mesh without optimization
import bpy
def export_voxel_model(filepath): bpy.ops.import_scene.obj(filepath="model.obj") bpy.ops.export_scene.fbx(filepath=filepath)
Correct Example
GOOD: Optimize voxel mesh before export
import bpy
def export_voxel_model(filepath):
Import voxel OBJ
bpy.ops.import_scene.obj(filepath="model.obj")
Select and enter edit mode
obj = bpy.context.active_object bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_all(action='SELECT')
Optimize: merge coplanar faces
bpy.ops.mesh.dissolve_limited(angle_limit=0.0001) bpy.ops.mesh.tris_to_quads()
bpy.ops.object.mode_set(mode='OBJECT')
Export optimized mesh
bpy.ops.export_scene.fbx(filepath=filepath)
Fix Suggestion
Add limited dissolve before export:
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.dissolve_limited(angle_limit=0.0001)
bpy.ops.object.mode_set(mode='OBJECT')Voxel Export Without LOD Generation
Id
blender-voxel-no-lod
Severity
medium
Category
optimization
Description
Voxel models for games should have LOD (Level of Detail) versions generated to maintain performance at various distances.
Detection
Type
regex
Pattern
export_scene\.(fbx|gltf)
File Patterns
- *.py
Correct Example
GOOD: Generate LODs for voxel model
import bpy
def generate_voxel_lods(obj, lod_ratios=[1.0, 0.5, 0.25, 0.1]): """Generate LOD versions of voxel mesh""" lods = []
for i, ratio in enumerate(lod_ratios):
Duplicate object
bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj bpy.ops.object.duplicate()
lod_obj = bpy.context.active_object lod_obj.name = f"{obj.name}_LOD{i}"
if ratio < 1.0:
Add decimate modifier
mod = lod_obj.modifiers.new(name="Decimate", type='DECIMATE') mod.ratio = ratio bpy.ops.object.modifier_apply(modifier="Decimate")
lods.append(lod_obj)
return lods
Chunk Mesh Generation on Main Thread
Id
chunk-mesh-main-thread
Severity
critical
Category
performance
Description
Generating chunk meshes synchronously on the main thread causes frame drops. Voxel chunk regeneration should be done asynchronously.
Detection
Type
regex
Pattern
GenerateMesh|RebuildMesh|UpdateChunk|RegenerateMesh
File Patterns
- *.cs
Anti Pattern Example
// BAD: Synchronous mesh generation blocks main thread public class VoxelChunk : MonoBehaviour { public void OnVoxelDestroyed(int x, int y, int z) { voxels[x, y, z] = 0; GenerateMesh(); // BLOCKS! Causes stutter }
void GenerateMesh() { // Complex mesh generation... for (int x = 0; x < size; x++) for (int y = 0; y < size; y++) for (int z = 0; z < size; z++) // Generate faces... } }
Correct Example
// GOOD: Async mesh generation with job system using Unity.Jobs; using Unity.Collections; using Unity.Burst;
public class VoxelChunk : MonoBehaviour { private bool isDirty = false; private MeshGenerationJob currentJob; private JobHandle jobHandle;
public void OnVoxelDestroyed(int x, int y, int z) { voxels[x, y, z] = 0; isDirty = true; // Flag for async rebuild }
void LateUpdate() { // Complete previous job if ready if (jobHandle.IsCompleted) { jobHandle.Complete(); ApplyMesh(currentJob.result); }
// Start new job if dirty if (isDirty && !jobHandle.IsCompleted) { currentJob = new MeshGenerationJob(voxels); jobHandle = currentJob.Schedule(); isDirty = false; } } }
[BurstCompile] struct MeshGenerationJob : IJob { public NativeArray<byte> voxels; public NativeList<Vector3> result;
public void Execute() { // Mesh generation runs on worker thread } }
Fix Suggestion
Move mesh generation to async/background thread:
- Unity: Use Job System with Burst
- Unreal: Use AsyncTask or GameThread delegates
- General: Move to separate thread, swap mesh on main thread
Voxel Chunk Size Too Large
Id
large-chunk-size
Severity
medium
Category
performance
Description
Chunk sizes larger than 32x32x32 cause slow mesh regeneration and excessive memory usage. Smaller chunks update faster but increase draw calls.
Detection
Type
regex
Pattern
chunkSize\s=\s(64|128|256)|CHUNK_SIZE\s=\s(64|128|256)
File Patterns
- *.cs
- *.cpp
- *.h
Anti Pattern Example
// BAD: Chunk too large - slow regeneration public const int CHUNK_SIZE = 64; // 262,144 voxels per chunk!
Correct Example
// GOOD: Balanced chunk size public const int CHUNK_SIZE = 16; // 4,096 voxels - fast updates // Or public const int CHUNK_SIZE = 32; // 32,768 voxels - balanced
Fix Suggestion
Use chunk sizes between 16 and 32:
- 16x16x16: Fast updates, more draw calls
- 32x32x32: Balanced for most games
- 64x64x64: Only for static content
Voxel Rendering Without Greedy Meshing
Id
no-greedy-meshing
Severity
high
Category
performance
Description
Rendering voxels without greedy meshing creates 6-12 triangles per voxel. Greedy meshing can reduce this by 90%+.
Detection
Type
regex
Pattern
GenerateVoxelFace|AddVoxelQuad|CreateCube|DrawVoxel
File Patterns
- *.cs
- *.cpp
- *.js
- *.ts
Anti Pattern Example
// BAD: Naive per-voxel face generation void GenerateMesh(int[,,] voxels) { for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { if (voxels[x,y,z] != 0) { // Creates 6 quads per visible voxel if (IsExposed(x+1,y,z)) AddQuad(Right); if (IsExposed(x-1,y,z)) AddQuad(Left); // ... etc } } } } }
Correct Example
// GOOD: Greedy meshing - merge coplanar faces // Reference: 0fps.net/2012/06/30/meshing-in-a-minecraft-game/
void GenerateMeshGreedy(int[,,] voxels) { // For each face direction for (int d = 0; d < 3; d++) { // For each slice in that direction for (int slice = 0; slice < size; slice++) { // Get 2D mask of visible faces bool[,] mask = GetSliceMask(d, slice);
// Greedy merge: find largest rectangles while (HasUnprocessedFaces(mask)) { // Find starting point var start = FindStart(mask);
// Expand width while same material int width = ExpandWidth(mask, start);
// Expand height while same material int height = ExpandHeight(mask, start, width);
// Create single quad for entire rectangle AddGreedyQuad(d, slice, start, width, height);
// Mark as processed MarkProcessed(mask, start, width, height); } } } }
Fix Suggestion
Implement greedy meshing for voxel rendering. See reference implementation at 0fps.net for algorithm details.
Voxel Animation Without Compression
Id
animation-no-compression
Severity
medium
Category
storage
Description
Storing full voxel frames for animation wastes storage. Delta compression or run-length encoding should be used.
Detection
Type
regex
Pattern
animationFrames|voxelFrames|frameData
File Patterns
- *.cs
- *.cpp
- *.ts
Anti Pattern Example
// BAD: Full copy of each animation frame public class VoxelAnimation { // 32x32x32 x 8 frames = 262,144 bytes per animation! public byte[,,,] frames = new byte[8, 32, 32, 32]; }
Correct Example
// GOOD: Delta-compressed animation frames public class VoxelAnimation { // Base frame stored fully public byte[,,] baseFrame = new byte[32, 32, 32];
// Delta frames store only changes public List<VoxelDelta>[] deltas = new List<VoxelDelta>[8];
public struct VoxelDelta { public ushort position; // Packed x,y,z public byte oldValue; public byte newValue; }
public byte[,,] GetFrame(int index) { var frame = (byte[,,])baseFrame.Clone();
for (int i = 1; i <= index; i++) { foreach (var delta in deltas[i]) { int x = delta.position & 0x1F; int y = (delta.position >> 5) & 0x1F; int z = (delta.position >> 10) & 0x1F; frame[x, y, z] = delta.newValue; } }
return frame; } }
Inconsistent Voxel Animation Frame Naming
Id
voxel-frame-naming
Severity
low
Category
organization
Description
Voxel animation frames should use consistent naming with zero-padded numbers for proper sorting.
Detection
Type
regex
Pattern
_\d\.vox$|_[a-z]\.vox$
File Patterns
- *.vox
Anti Pattern Example
BAD: Inconsistent naming
character_walk_1.vox character_walk_2.vox character_walk_10.vox # Sorts wrong!
Correct Example
GOOD: Zero-padded frame numbers
character_walk_01.vox character_walk_02.vox character_walk_10.vox
ALSO GOOD: Explicit naming
character_idle_frame01.vox character_idle_frame02.vox
Missing Shared Palette File
Id
voxel-no-palette-file
Severity
low
Category
organization
Description
Voxel projects should have a shared palette file for consistency across all models. MagicaVoxel palettes are 256x1 PNG files.
Detection
Type
file_exists
Expected Files
- palette.png
- palette/*.png
- assets/palette.png
File Patterns
- *.vox
Correct Example
Project structure with shared palette
project/ palette/ main_palette.png # Master palette character_palette.png # Character-specific environment_palette.png models/ character.vox prop.vox