SpaceMap sample overview
Updated: May 7, 2026
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.
- 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
- 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.
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.
| File / Scene | What it demonstrates | Key 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 |
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.
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.
- 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.