Wiki 9Minecraft Wiki 9Minecraft

Custom Blocks: Vanilla Voxel Shapes and Culling

Define custom block occlusion, face culling, and bounding boxes in Bedrock add-ons.

5Sections
3Code examples
3Known errors

In Minecraft Bedrock Edition, the way a block interacts with adjacent blocks, casts shadows, and collides with entities is determined by its geometry, culling rules, and box components. While full-cube blocks handle face culling automatically, custom 3D models require explicit instructions so the engine knows which neighbor faces to hide and where players can walk or click. You reach for these tools whenever you build slabs, stairs, pillars, or intricate furniture that should not make adjacent blocks turn invisible.

How Bedrock Handles Block Shapes

Wait-free rendering in Minecraft relies heavily on face culling: skipping the drawing of block faces that are completely pressed against another solid block. In the Java edition, a unified concept called a VoxelShape controls collision, selection, and light occlusion all at once. In Bedrock Edition, these responsibilities are split across multiple components in the behavior pack and culling definitions in the resource pack.

When you assign the standard unit cube identifier to a custom block, the engine treats it as an opaque 16x16x16 volume. The moment you switch to a custom geometry file in the `minecraft:geometry` component, Bedrock assumes your block might have transparent gaps. Without further configuration, it stops culling the faces of adjacent full blocks to prevent players from seeing into the void, and it defaults the physical hitboxes back to a full cube unless told otherwise.

Defining Physical and Selection Bounds

Physical movement and player cursor interaction are controlled by `minecraft:collision_box` and `minecraft:selection_box`. Both components measure their bounds in block pixels (1/16th of a block) using an `origin` array and a `size` array. The origin is always measured from the bottom-center of the block space, making a full block start at `[-8, 0, -8]` with a size of `[16, 16, 16]`.

Prior to format version 1.21.50, each component only accepted a single box. Modern format versions allow a `boxes` array inside `minecraft:collision_box`, letting you assemble compound voxel shapes like L-shaped stair steps or hollow cauldrons where entities can actually stand inside the model.

PropertyWhat it doesNotes
originSets the starting corner of the box `[x, y, z]`.Ranges from -8 to 8 on X/Z, and 0 to 16 on Y.
sizeSets the width, height, and depth `[w, h, d]`.`origin + size` must not exceed `[8, 16, 8]` (or 24 on Y for fences).
boxesArray of `origin` and `size` pairs for compound shapes.Supported on `minecraft:collision_box` in 1.21.50 and newer.
booleanSetting the component to `false` disables the box entirely.Useful for walk-through plants or non-targetable air markers.
BP/blocks/stone_step.json
{
  "format_version": "1.21.50",
  "minecraft:block": {
    "description": {
      "identifier": "wiki:stone_step"
    },
    "components": {
      "minecraft:geometry": {
        "identifier": "geometry.wiki.stone_step",
        "culling": "wiki:culling.stone_step"
      },
      "minecraft:material_instances": {
        "*": {
          "texture": "stone",
          "render_method": "opaque"
        }
      },
      "minecraft:selection_box": {
        "origin": [-8, 0, -8],
        "size": [16, 16, 16]
      },
      "minecraft:collision_box": {
        "boxes": [
          {
            "origin": [-8, 0, -8],
            "size": [16, 8, 16]
          },
          {
            "origin": [-8, 8, 0],
            "size": [16, 8, 8]
          }
        ]
      }
    }
  }
}

Built-in Full Cube Geometry

If your custom block is a standard 16x16x16 solid block, you do not need to create a `.geo.json` model file or write custom culling rules. Bedrock includes a built-in geometry identifier specifically for this purpose: `minecraft:geometry.full_block`.

Using `minecraft:geometry.full_block` inside the `minecraft:geometry` component tells the engine to use the hardcoded vanilla cube shape. It automatically enables full neighbor face culling, proper ambient occlusion, and standard UV mapping across all six faces, matching the exact rendering performance of vanilla stone or dirt.

BP/blocks/polished_granite_brick.json
{
  "format_version": "1.20.80",
  "minecraft:block": {
    "description": {
      "identifier": "wiki:polished_granite_brick"
    },
    "components": {
      "minecraft:geometry": "minecraft:geometry.full_block",
      "minecraft:material_instances": {
        "*": {
          "texture": "wiki_polished_granite_brick",
          "render_method": "opaque"
        }
      }
    }
  }
}

Block Culling Rules and Occlusion

When two custom blocks sit next to each other, or when a custom block sits against a vanilla block, the `culling` property inside `minecraft:geometry` controls which parts of your model disappear. The string you provide here matches a file inside the `RP/block_culling/` directory of your resource pack.

A block culling file maps individual bones or cubes from your geometry to a specific neighbor direction (`up`, `down`, `north`, `south`, `east`, `west`). By setting the `condition` to `same_culling_layer` or `same_block`, you can make glass-like blocks or connected slabs hide their interior seams when placed side by side, without causing x-ray glitches against full solid blocks.

RP/block_culling/stone_step.json
{
  "format_version": "1.20.60",
  "minecraft:block_culling_rules": {
    "description": {
      "identifier": "wiki:culling.stone_step"
    },
    "rules": [
      {
        "direction": "down",
        "geometry_part": {
          "bone": "base_slab",
          "cube": 0,
          "face": "down"
        }
      },
      {
        "direction": "north",
        " condition": "same_block",
        "geometry_part": {
          "bone": "base_slab",
          "cube": 0,
          "face": "north"
        }
      }
    ]
  }
}

Light Dampening and Shadow Occlusion

Visual shape and physical bounds do not automatically stop skylight or blocklight from passing through your block. A custom geometry block defaults to letting some or all light pass unless you pair it with `minecraft:light_dampening`.

This component takes an integer from `0` (completely clear to light, like air or glass) to `15` (completely opaque, blocking all light like stone). For partial shapes such as slabs or stairs, setting `minecraft:light_dampening` to `0` or a low value prevents dark, unnatural shadow patches from forming directly underneath the block when placed in sunlight.

Which versions this applies to

Applies to Bedrock Edition 1.20.60+ for stable `minecraft:geometry`, `minecraft:collision_box`, `minecraft:selection_box`, and `RP/block_culling/`. Multiple collision boxes via the `boxes` array require format_version 1.21.50 or newer. No experimental toggles are required.

When it does not work

What you seeWhyThe fix
Adjacent blocks turn invisible (X-Ray effect) when placing the custom block next to stone or dirt.You used `minecraft:geometry.full_block` with a transparent texture and `opaque` render method, or you omitted `minecraft:geometry` and used a legacy ` RP/blocks.json` shape that culls neighbors.Use a custom `.geo.json` model for non-full blocks, or change the `render_method` in `minecraft:material_instances` to `alpha_test` or `blend` so the engine stops culling neighbor faces.
Content Log error: `[Blocks][error]-wiki:stone_step | minecraft:collision_box: box is out of bounds` and the block has no collision in-game.The sum of `origin` and `size` on the X or Z axis exceeds the `[-8, 8]` boundary, or the Y axis goes below `0`.Ensure `origin[0] + size[0] <= 8` and `origin[2] + size[2] <= 8`. Remember that X and Z origins start at `-8` for the edge of a block, not `0`.
Content Log warning: `Failed to find culling rule 'wiki:culling.stone_step'` and internal faces remain visible.The culling file is either placed in the behavior pack instead of the resource pack, or the `identifier` inside the culling JSON does not match the string in `minecraft:geometry`.Move the culling JSON file to `RP/block_culling/` and verify that its `description.identifier` exactly matches the `culling` field in your behavior pack block file.

Reference, straight from the game files

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