Wiki 9Minecraft Wiki 9Minecraft

Custom Block Culling Rules

Hide unseen geometry parts on custom blocks using resource pack culling definitions.

5Sections
3Code examples
3Known errors

Block culling removes hidden geometry faces when a custom block sits directly against another block. You reach for culling rules when building custom glass, connected pipes, or multi-cube models that suffer from frame-rate drops or Z-fighting when placed in large clusters. Defining a culling file in your resource pack and linking it to your block's geometry component gives you per-bone and per-face control over what the game renders.

How Block Culling Works in Bedrock

When you use the standard full-block unit cube, Minecraft Bedrock automatically hides any face touching an opaque neighbor. The moment you switch to a custom model using the "minecraft:geometry" component, the engine can no longer assume your block fills the entire 16x16x16 space. By default, it draws every single polygon in your model, even faces pressed flat against stone or dirt.

To fix this without forcing the engine to guess your model's shape, Bedrock uses a dedicated culling system split across both packs. In the Resource Pack, a JSON file inside the "block_culling/" directory maps specific bones, cubes, and faces of your Blockbench model to directional neighbor checks. In the Behavior Pack, the "minecraft:geometry" component binds that culling rule to the block by its identifier.

This approach is essential for two reasons: rendering performance and visual cleanliness. If a player builds a wall out of 500 custom framed-glass blocks, unculled inner faces will tank the frame rate and create ugly overlapping translucent surfaces. Proper culling strips those interior faces out of the mesh before it goes to the GPU.

Linking Culling in the Behavior Pack

Before writing the culling rules themselves, your block needs to know which culling definition to use. This happens inside the expanded object form of the "minecraft:geometry" component in your Behavior Pack block file.

If you normally write "minecraft:geometry": "geometry.my_block", you must convert that shorthand string into an object containing the "identifier" and "culling" properties. The "culling" string must have a namespace—and unlike geometry identifiers, it cannot use the "minecraft:" namespace. It must use your own pack's custom namespace.

BP/blocks/framed_glass.json
{
  "format_version": "1.20.60",
  "minecraft:block": {
    "description": {
      "identifier": "wiki:framed_glass"
    },
    "components": {
      "minecraft:geometry": {
        "identifier": "geometry.wiki_framed_glass",
        "culling": "wiki:cull.framed_glass"
      },
      "minecraft:material_instances": {
        "*": {
          "texture": "wiki_framed_glass",
          "render_method": "blend"
        }
      }
    }
  }
}

Writing the Block Culling File

Block culling files live in the "RP/block_culling/" folder of your Resource Pack. The file name does not technically matter to the engine, as the game matches the rule using the "identifier" inside the JSON, though naming the file after your block keeps the pack organized.

Inside "minecraft:block_culling_rules", you define a "rules" array. Each entry in this array targets one specific part of your geometry and tells the game which neighboring direction to check. If a neighbor block in that direction meets the culling condition, the targeted geometry part disappears.

You can cull an entire bone, a whole cube inside a bone, or a single face on a specific cube. When targeting a cube, you index it using a zero-based integer corresponding to its order in the geometry file's "cubes" array for that bone.

FieldWhat it doesNotes
directionSpecifies which adjacent block space triggers this rule.Accepts "north", "south", "east", "west", "up", or "down".
geometry_part.boneNames the bone in the geometry file to target.Required for every rule. Case-sensitive.
geometry_part.cubeZero-based index of the cube inside the chosen bone.Optional. Omit this and "face" to cull the entire bone.
geometry_part.faceThe specific UV face of the targeted cube to hide.Optional. Requires "cube" to be set. Accepts the six cardinal directions.
conditionDetermines how the neighbor is evaluated for culling.Optional. Used for matching specific neighbor criteria like identical block types.
RP/block_culling/framed_glass_culling.json
{
  "format_version": "1.20.60",
  "minecraft:block_culling_rules": {
    "description": {
      "identifier": "wiki:cull.framed_glass"
    },
    "rules": [
      {
        "direction": "north",
        "geometry_part": {
          "bone": "frame",
          "cube": 0,
          "face": "north"
        }
      },
      {
        "direction": "south",
        "geometry_part": {
          "bone": "frame",
          "cube": 0,
          "face": "south"
        }
      },
      {
        "direction": "up",
        "geometry_part": {
          "bone": "top_cap"
        }
      }
    ]
  }
}

Matching the Geometry Structure

Your culling rules are tightly coupled to how your model is structured in Blockbench. If you move a cube from one bone to another, or reorder cubes inside a bone, the integer index in "geometry_part.cube" will point to the wrong piece of geometry.

Because cube indices are fragile when editing models, it is often cleaner to separate parts that get culled together into their own dedicated bones. For example, if you are making a pipe or fence post where an entire connector arm disappears when nothing is next to it, put that arm in a bone named "north_arm" and omit the "cube" and "face" keys in your culling rule. If you are only stripping the outer faces of a single cube, keep that cube at index 0 of a named bone.

RP/models/blocks/framed_glass.geo.json
{
  "format_version": "1.12.0",
  "minecraft:geometry": [
    {
      "description": {
        "identifier": "geometry.wiki_framed_glass",
        "texture_width": 16,
        "texture_height": 16,
        "visible_bounds_width": 2,
        "visible_bounds_height": 2,
        "visible_bounds_offset": [0, 0.5, 0]
      },
      "bones": [
        {
          "name": "frame",
          "pivot": [0, 0, 0],
          "cubes": [
            {
              "origin": [-8, 0, -8],
              "size": [16, 16, 16],
              "uv": {
                "north": {"uv": [0, 0], "uv_size": [16, 16]},
                "east": {"uv": [0, 0], "uv_size": [16, 16]},
                "south": {"uv": [0, 0], "uv_size": [16, 16]},
                "west": {"uv": [0, 0], "uv_size": [16, 16]},
                "up": {"uv": [0, 0], "uv_size": [16, 16]},
                "down": {"uv": [0, 0], "uv_size": [16, 16]}
              }
            }
          ]
        },
        {
          "name": "top_cap",
          "pivot": [0, 0, 0],
          "cubes": [
            {
              "origin": [-4, 15, -4],
              "size": [8, 1, 8],
              "uv": [0, 0]
            }
          ]
        }
      ]
    }
  ]
}

Rotation and Transformation Caveats

When you rotate a custom block using the "minecraft:transformation" component inside permutations (for example, rotating a directional pillar or stair block based on cardinal direction), Bedrock rotates the culling directions along with the geometry.

This means you only need to write your culling rules for the default, unrotated state of the model in Blockbench. If your rule says to cull the "north" face of cube 0 when a block is to the "north", and a permutation rotates the block 90 degrees clockwise around the Y axis, the game automatically checks the "east" neighbor and hides the newly east-facing polygon.

Which versions this applies to

Stable in format_version 1.20.60 and later. No experimental toggles are required to use block_culling_rules or the culling property on minecraft:geometry.

When it does not work

What you seeWhyThe fix
Content Log Error: [Blocks][error]-wiki:framed_glass | minecraft:geometry | culling: Invalid culling identifierYou either forgot to include a namespace in the culling identifier (e.g., writing "cull.framed_glass" instead of "wiki:cull.framed_glass"), or you used the reserved "minecraft:" namespace.Ensure the identifier in both the Behavior Pack geometry component and the Resource Pack culling description uses your custom namespace separated by a colon.
The block loads without errors, but faces never cull when placed next to solid blocks.The bone name in "geometry_part" does not exactly match the bone name in your .geo.json file, or your Resource Pack format_version in the culling file is older than 1.20.60.Check that "format_version" is "1.20.60" or higher in both the block and culling JSON files, and verify the exact spelling and capitalization of your bone names.
Placing a custom translucent block next to another identical custom block still shows the inner faces between them.By default, standard culling rules only trigger when the neighboring block is a full, opaque cube. A neighbor that also uses custom geometry or non-opaque materials will not trigger the default neighbor check.Make sure your culling rule includes the appropriate condition check for matching blocks or non-full neighbors, or verify that the neighbor block is actually considered solid by the engine.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.