Skip to content

z02. Features

Bram Stout edited this page Jan 31, 2026 · 1 revision

Foreground and Background Chunks

MiEx splits up the exported area into "export chunks". Each export chunk can be tagged as either foreground or background. This is mainly an organisational thing. The raytracing optimiser does use different fullness threshold values for foreground and background chunks, but apart from that it's purely organisational. It places foreground chunks into a foreground Xform and background chunks into a background Xform. This can be useful, since chunk data is payloaded in, and having foreground and background chunks separated into different prims, makes it easy to load or unload all background or foreground chunks.

Raytracing Optimiser

Most offline renderers (like Renderman, Arnold, Octane, Redshift, VRay, and Cycles) use raytracing. Unfortunately, most exports generate meshes that aren't efficient for these renderers to render out. Raytracing renderers need to trace rays against the polygons of the meshes. This takes a lot of time, especially since a ray won't hit the fast majority of the polygons in a scene. In order to speed things up, renderers first test the ray against the bounding boxes of meshes. If they don't hit, then the renderer knows that ray won't hit any polygons in that mesh. If it does hit, then it needs to test the ray against the polygons of that mesh. This is an oversimplification, but still explains well enough what this optimiser is about. The reason why modern renderers are able to render so fast, is because they can cull away most of the meshes in a scene very quickly.

However, most exporters when they export out a world create meshes that span large parts of the world or even the entire world! If you look at their bounding boxes and how much of those bounding boxes are actually occupied by blocks, you'll notice that it's often only a small percentage. Because practically all meshes have bounding boxes with large voids in them, when a ray needs to be traced, it'll hit the bounding box of almost every mesh in our scene. This somewhat negates the culling that the renderers are trying to do, slowing down rendering.

MiEx solves this by splitting these large meshes up into smaller meshes, so that their bounding boxes will have less empty space in them. This allows renderers to more efficiently cull polygons that a ray will never hit. The downside, is that there will be a lot more meshes. Modern raytracing renderers don't have much of a problem with this and this optimising strategy will still give a net performance increase during rendering. However, DCC's and rasterisation-based renderers (like viewports, Unreal Engine, and Unity) won't get any benefit from bounding boxes having less empty space in them (because they don't trace rays) and instead can get slowed down a lot by having a lot of meshes.

In order to determine when a mesh has been split up enough, it uses a "fullness threshold". Basically, it calculates how much of the mesh's bounding box is occupied by blocks, creating a number ranging from 0 to 1. If that number is higher than the fullness threshold, it stops splitting the mesh up. Otherwise, it keeps going. To keep the number of meshes somewhat in control, MiEx has two fullness threshold values. One for foreground chunks and one for background chunks. Normally the foreground chunks' fullness threshold is a relatively high number because this is where optimising is really important. For background chunk, the fullness threshold can be very low. If the fullness threshold of a value of 0, then it disables the optimiser.

To solve this issue, MiEx generates two versions of every mesh: a proxy version and a render version. The proxy version is one big mesh that DCC's and rasterisation-based renderers can efficiently handle. The render version is the optimised version that has been split up into many smaller meshes. By default only the proxy versions are loaded in. To load in the render version, you set the variant set MiEx_LOD to the variant render. This causes USD to also load in the render version of each mesh. The proxy and render versions are properly tagged in USD, so that your viewport will still use the proxxy version and any raytracing renderers will use the render version.

Face Optimiser

The face optimiser tries to combine faces together into larger faces, whenever possible. This reduces polycount. This optimiser works with atlases and things like randomly rotated textures. Atlases, by default, repeat each texture a few times. This allows the optimiser to combine faces and let the texture repeat. How big the combined face can get, is limited by the amount of repeats in the atlas. For randomly rotates textures, the optimiser will see if it can combine the faces without it changing the rotation. If it can't, then it simply won't combine the faces.

Individual Blocks

By default, all blocks that use the same texture are combined into one mesh. This creates more efficient sets. But sometimes you want every occurrence of a certain block to be exported out as individual instances of that block, rather than all combined into one mesh. This allows you to replace one specific block with a rig for that block so that you can animate it. Or, it allows you to place something at every such block, like a flame particle and a light on every torch.

You can tell MiEx which blocks need to be exported out as individual blocks in the miex_config.json files. You can also tell MiEx to export every single block out into an individual block in the UI, if you're feeling adventurous. MiEx will then create a base model for each unique block and then create instances of that base model at every occurrence of that block in the world. More info about the miex_config.json file can be found here.

Level-of-Detail

MiEx can easily handle giant worlds and giant exports. But not every DCC or renderer can handle it as well. To help with this, MiEx has a Level-of-Detail system which helps to reduce polygon count in the far background. It does this by exporting the far backgrounds at a lower resolution. So, rather than exporting out each block on its own, it combines 2x2x2 blocks into one bigger block, or 4x4x4, or 8x8x8, or 16x16x16. When turning LOD on, you can specify the area where MiEx should export out in full resolution. Outside of that area, MiEx will gradually use lower and lower resolutions for the blocks.

MiEx achieves this lowering of the resolution, by down-sampling the world. In other words, it takes the 2x2x2, 4x4x4, 8x8x8, or 16x16x16 block volume and chooses one block to represent that entire volume. In order to control how MiEx chooses that block, in the miex_config.json you can give different blocks different priority values. The higher the value, the more important that block is and so the more likely that block will be chosen. A value of 0 will effectively ban that block from being chosen.

When exporting out, MiEx will basically export out scaled up versions of those chosen blocks in the far backgrounds. In order to make it not look like it's just scaled up, MiEx will also scale up the UVs to compensate, so that each pixel will still have the same world size regardless of the Level-of-Detail. There are certain blocks however, where this scaling on the UVs won't work that well. In those cases, you can add those blocks to the lodNoUVScale setting in the miex_config.json. More info about the miex_config.json file can be found here.

The amount by which is down-samples the world is based on the distance from the centre of the LOD area that should be exported out in full resolution. In some cases, you can very easily see the down-sampling in the distance. To help with this, you can also specify a LOD Y Detail value. This effectively increases the resolution on the Y axis. The default value of 4 means that it will down-sample to 1x1x1, 2x1x2, 4x1x4, 8x2x8, or 16x4x16.

For an overview of how to use the LOD system, visit the Usage chapter of the Wiki.

Remove caves

It is very common to export out the overworld where the camera is always above the surface. In those cases, caves can cause a lot of geometry to be created, which can take time to clean up. MiEx has a built in algorithm that detects caves and removes them. This can create holes in the world, for which it has a second algorithm that can fill up those holes.

MiEx detects whether a block is inside of a cave or not. If it's inside of a cave and the cave removal algorithm has been enabled, then it won't export out that block. The algorithm works in two steps. In the first step, it looks at the height map of the world in a certain radius (removeCavesSurfaceRadius). If the heightmap within that radius in less than the current block's height plus removeCavesSearchEnergy, then it deems the current block to be near the surface and thus not in a cave. Otherwise, it moves on to step two. The second step works by searching in a square with the current block at its centre and a radius of removeCavesSearchRadius. Within that square, it looks for non-cave blocks. For any non-cave block, it increments a counter. If that counter reaches removeCavesSearchRadius + 1 then it deems the current block not in a cave and stops there. The algorithm has an energy counter that starts off at removeCavesSearchEnergy * 3. If in the square it finds water, it does nothing and moves the square up one block. If in the square it finds air, it reduces the energy by removeCavesAirCost and moves the square up one block. If it didn't find water or air, it reduces the energy by removeCavesCaveBlockCost and moves the square up one block. When the energy reaches zero and we still haven't reached the surface or encountered too many non-cave blocks, then we deem the current block to be in a cave.

miex_config.json allows you to customise the values used in the algorithm. More info about the miex_config.json file can be found here.

Custom noise generator

Minecraft randomly rotates the textures of certain blocks. If achieves this using the block state file for that block, by specifying multiple variants of the same model but with different rotations. Minecraft randomly picks one of these variants uniformly without any regard of neighbouring variants. This can cause obvious patterns to emerge. MiEx uses a custom noise pattern to randomly pick one of these variants, specifically to reduce the patterns and create more pleasing looking randomly rotated textures.

Biome colours

MiEx is able to read the biome for every block and calculate the biome tints based on the information in the resource packs. It then exports out these biome tints as vertex colours which can then be used in the materials to tint the grayscale textures. MiEx is also able to blend the biome tints, just like Minecraft. Because MiEx gathers the biome tints from the resource packs, it's very easy to modify them, or to add custom biomes. More info about the biome colours can be found here.

Animated textures

Minecraft makes use of animated textures. It does this by having a .mcmeta file next to the texture file, which contains information about the animation. MiEx is able to read this and provide this information to the USD Material templates so that they can set up proper networks to handle animated materials.

MiEx is also able to randomly offset the animation start frames for different blocks, to create more pleasing images. For example, if you have a row of fire blocks, they will all have different offsets in the animation rather than all showing the same frame at the same time. This can make things look more natural. Which blocks receive this random offset, can be specified in miex_config.json. More info about the miex_config.json file can be found here.

Connected Textures

MiEx supports connected textures using Optifine's CTM format. More info about connected texture can be found here.

Entities

MiEx is able to read in entities as well. Currently, MiEx is only able to export out paintings and item frames (including items and maps in item frames), but it can be extended to be able to export out different entities as well in the future.

Atlases

Minecraft uses a lot of different textures that are all in their own file. This means that MiEx has to create a lot of materials as well. This can slow things down, so in order to help speed things up, MiEx has support for atlases. An atlas in a big texture that contains the smaller textures located in a grid. MiEx comes with an atlas creator tool. More info about the texture atlases can be found here.

Mod support

MiEx is able to support mods, assuming that they store world data in the same way that vanilla Minecraft does. If it specifies a block name, then MiEx will try to find the block state for it. So, all that's needed for MiEx to support custom blocks from mods, is for MiEx to have a resource pack enabled that specifies a block state (and optional custom models) for that custom block. The same is for custom biomes. More info about mod support can be found here.

More powerful block states

MiEx has a few additions to Minecraft's block state files. MiEx add an implicit property where you can query neighbouring blocks. This allows you to recreate complex models from mods where the block connects to other blocks. It also allows you to do things like create connected textures. More info about block states can be found here.

Clone this wiki locally