Develop

SpaceMap sample overview

Updated: May 7, 2026

Overview

This sample demonstrates how to integrate a large virtual terrain environment with physical room boundaries detected by Meta Quest’s Scene API. It uses MRUK’s SpaceMapGPU to generate a 2D texture representation of your room, then blends that data into shader rendering and runtime mesh modification to create seamless indoor-outdoor transitions.

What you will learn

  • Use SpaceMapGPU to generate a 2D texture from MRUK room data
  • Query room boundaries by iterating MRUK.Instance.Rooms and using MRUKRoom.IsPositionInRoom()
  • Chain MRUK events (RoomUpdatedEvent → texture generation → mesh flattening) for async operations
  • Use projective texturing in shaders to map room data onto arbitrary geometry
  • Modify mesh vertices at runtime based on spatial queries without creating seams

Requirements

  • Device: Meta Quest with Scene API support
  • Development environment: Unity 2022.3 or later with MR Utility Kit package installed
For detailed platform setup, see Unity development setup.

Get started

Clone the Unity-MRUtilityKitSample repository and open the project in Unity. Navigate to Assets/MRUKSamples/SpaceMap/ and open SpaceMap.unity. Build and deploy to your Quest device following the instructions in the repository README.

Explore the sample

File / SceneWhat it demonstratesKey concepts
SpaceMap.unity
Event wiring between MRUK, SpaceMapGPU, and TerrainFlattener
Unity event pipeline, component orchestration
Scripts/TerrainFlattener.cs
Runtime mesh modification based on room boundaries
Spatial queries, vertex manipulation, neighbor propagation
Shaders/TerrainSpaceMap.shader
Projective texture blending with dual render pipeline support
Projection-view matrix transformation, texture blending, URP/BiRP compatibility
Terrain/M_Terrain.mat
Material configuration with terrain, grass, dirt, and SpaceMap textures
Shader parameter setup
Terrain/Terrain.fbx
Large-scale terrain mesh (scaled 2000x in scene)
Environment geometry

Runtime behavior

When you run this scene, you see a massive grassy terrain that extends far beyond your physical room. The area corresponding to your actual room appears as a flat, dirt-textured floor at a consistent height, while the terrain outside the room boundaries remains grassy and hilly.
As you move around, the boundary between the outdoor terrain and indoor floor remains stable and seamless, with no visible seams or sudden transitions. The room area updates automatically if the Scene API detects room boundary changes.

Key concepts

GPU-generated room textures

The sample uses SpaceMapGPU to create a 2D texture representing the room layout. When RoomUpdatedEvent fires, the scene calls SpaceMapGPU.StartSpaceMap() to generate this texture. The component provides both the texture and a _SpaceMapProjectionViewMatrix that transforms world-space positions into texture coordinates. The shader samples this texture to determine which areas of the terrain are inside or outside the room boundaries. See the component configuration in SpaceMap.unity.

Event-driven mesh flattening

The TerrainFlattener listens to SpaceMapGPU.SpaceMapCreatedEvent to trigger mesh modification only after the room texture is ready. The flattening happens in two passes: first, vertices inside the room are set to terrainHeight, then immediate neighbors of flattened vertices are also flattened to prevent visible seams. This pattern ensures the mesh matches the room bounds without race conditions between room detection and geometry updates. See TerrainFlattener.cs.

Projective texturing in shaders

The TerrainSpaceMap shader receives _SpaceMapProjectionViewMatrix and uses it to transform vertex positions into UV coordinates for sampling the SpaceMap texture:
float4 clipPos = mul(_SpaceMapProjectionViewMatrix, i.worldPos);
clipPos /= clipPos.w;
float2 uv = clipPos.xy * 0.5 + 0.5;
The shader samples the SpaceMap’s red channel to blend between grass (outside room) and dirt (inside room), creating a continuous visual transition that aligns perfectly with the mesh flattening. See the full shader at Shaders/TerrainSpaceMap.shader.

Dual render pipeline support

The shader includes separate SubShader blocks for URP and Built-in Render Pipeline, using PackageRequirements directives to select the appropriate version at build time. This ensures the sample works regardless of which render pipeline your project uses, without requiring manual shader switching or duplicate materials.

Extend the sample

  • Change the terrain theme: Replace tex_Terrain.png and Ground.jpg with custom textures, or modify the shader to blend between different outdoor/indoor materials like snow and wood flooring.
  • Add vertical room awareness: Extend TerrainFlattener to respect ceiling height by querying room anchor data and modifying vertices that exceed the ceiling boundary.
  • Combine with placement logic: Study the SceneDecorator sample to see how SpaceMapGPU textures can drive object placement masks in addition to rendering.