Roof attributes and shapes
RoofsLayer draws real 3D roofs (gabled, hipped, domes, …) on top of your own fill-extrusion buildings and shortens each building's walls by the roof it draws. It reads plain attributes from a vector (or GeoJSON) source. This page lists the attributes a tileset needs, how each value is read, and how every OpenStreetMap roof:shape value is drawn.
Tileset requirements
- A vector or GeoJSON source with one feature per building outline and per building part (polygons or multipolygons).
- Feature ids. Every feature needs an id (numeric ids, or
promoteIdon the source). The layer uses them to shorten walls through feature state. - Attribute names follow Overture's building schema by default. Other sources map their names with
fields, e.g.fields: { roof_shape: 'roof:shape', roof_angle: 'roof:angle' }. - Your walls: a
fill-extrusionlayer on the same source, passed asextrusionLayer. Give itfilter: ['!=', ['get', 'has_parts'], true], so outlines drawn by their parts don't hide those parts' roofs.
Only buildings with a recognised roof_shape (and a height) get a roof; every other building keeps its flat extrusion.
Attributes
| Attribute | Required | Type | Meaning | OSM tag | Overture column |
|---|---|---|---|---|---|
roof_shape | yes | string | Roof shape, see Roof shapes | roof:shape | roof_shape |
height | yes | number (m) | Top of the building or part, including its roof | height (or building:levels, below) | height (or num_floors, below) |
min_height | no (0) | number (m) | Bottom of the part (for parts that start above ground) | min_height / building:min_level | min_height (or min_floor) |
roof_height | no | number (m) | Height of the roof alone, eaves to top | roof:height (or roof:levels) | roof_height |
roof_angle | no | number (°) | Pitch of the roof faces; used only when there is no roof_height | roof:angle | — |
roof_direction | no | number (°) or N/E | Compass bearing the main roof face looks toward | roof:direction | roof_direction |
roof_orientation | no | along/across | Ridge along or across the longest side of the outline | roof:orientation | roof_orientation |
roof_color | no | CSS colour | Roof colour | roof:colour | roof_color |
roof_material | no | string | Picks a roof colour when no roof_color is set | roof:material | roof_material |
facade_color | no | CSS colour | Wall colour (gable ends; the extrusion too with wallColors: true) | building:colour | facade_color |
facade_material | no | string | Picks a wall colour when no facade_color is set | building:material | facade_material |
has_parts | recommended | boolean | The outline is drawn by its building:parts: no roof of its own | derived (a part lies inside the outline) | has_parts |
How values are read:
- Numbers may be numbers or numeric strings (
"12"). Non-numeric values are ignored. heightmust be greater thanmin_height, or the building gets no roof.roof_heightmust be positive. It is capped at the part's full height span (a part that is all roof, like a spire, can be).roof_anglemust be between 0 and 90 (exclusive).roof_directiontakes degrees clockwise from north, or a 16-point compass value (N,NNE, …NNW). It snaps to the nearest wall within the precision it was written with, as OSM2World does: 45° for compass letters, 10° for whole degrees, 0.5° for decimals.- Numbers written with a decimal comma (
3,5) are read as3.5. - Without
height,num_floorsgives it (3 m a floor, plusroof_heightwhen tagged), andmin_floorgivesmin_height. UsebuildingHeight()/buildingBase()for the walls so they match. roof_orientationother thanalong/acrossis ignored.has_partsacceptstrue,1,"true"or"yes".- Shape names are matched case-insensitively, and
_/-are interchangeable (half-hipped,half_hippedandHalf-Hippedare the same).
Roof height
The roof is drawn inside the building's height: walls are shortened by the roof height, so the top of the roof sits at height.
roof_heightif set, capped atheight − min_height.- Otherwise
roof_angle, if set:tan(angle) × run, capped atheight − min_height. The run is the horizontal distance one roof face covers:- gabled-family shapes, butterfly, crosspitched: half the width across the ridge;
- skillion: the full width;
- sawtooth: one tooth (the angle sets every tooth);
- pyramidal, cone: the radius (half the shorter side).
- Ignored for curved roofs (
dome,onion,round), which have no single pitch.
- Otherwise a default height:
tan(30°) ×half the shorter side (half a tooth for sawtooth), or the radius for curved roofs. That is a 30° pitch for gabled-family roofs; a skillion, whose face spans the full width, comes out shallower. The default is capped at half ofheight − min_height, and a building whose default comes out under 0.5 m gets no roof.
Roof direction and the ridge
Roofs are laid out on the outline's tight bounding box, with the ridge along one axis:
- With
roof_direction, the main face looks toward that bearing and the ridge runs perpendicular to it. A skillion slopes down toward the bearing; sawtooth teeth slope down toward it, with their glazing facing away. - Otherwise the ridge runs along the longest side, or across it with
roof_orientation=across. hipped,half_hipped,hipped_and_gabledandmansardalways put the ridge on the longer axis of the box, since their end slopes assume it.
Roof shapes
Drawn as their real shape
roof_shape | Drawn as | In Overture |
|---|---|---|
gabled | Two slopes meeting at a central ridge; vertical gable ends | yes |
saltbox | Gable with the ridge off-centre (moved by a third of the half-width), so one slope is longer | yes |
hipped | Four slopes; the ridge is shortened by the hips at each end | yes |
half_hipped | Gable ends up to half height, small hips above (jerkinhead) | yes |
side_hipped | Hipped at one end, gabled at the end where other parts are attached (both ends hipped if unknown) | no |
side_half_hipped | The same with a half hip | no |
hipped_and_gabled | Hips up to half height, small vertical gables above (Dutch gable) | no |
gambrel | Barn roof: steep lower part on both long sides, shallower upper part; gable ends | yes |
mansard | Gambrel profile on all four sides | yes |
skillion | One slope, high at the back, low toward roof_direction | yes |
round | Half-cylinder vault along the ridge (8 facets) | yes |
bellcast_gable | Gable whose slopes flatten into a flare near the eaves | no |
butterfly | V shape: eaves at full height on both long sides, valley along the middle | no |
crosspitched | Two crossing gables: gable ends on all four sides, meeting at a central peak | no |
sawtooth | Repeated single slopes (~8 m teeth, whole number across the building) with near-vertical glazing | yes |
pyramidal | Slopes from every outline edge up to a central apex | yes |
cone | Slopes from every outline point up to a central apex: a true cone on a round outline, and the whole footprint covered on any other | no |
dome | Hemisphere-like dome on a circle inside the outline (corners of a square outline stay flat) | yes |
onion | Onion dome (OSM Buildings profile) | yes |
Near-vertical faces (gable ends, the small gables of hipped_and_gabled, sawtooth glazing) take the wall colour; sloped faces take the roof colour.
Aliases (drawn as the nearest shape)
roof_shape | Drawn as | Notes |
|---|---|---|
spherical | dome | Overture's name for a dome |
pyramid | pyramidal | Synonym |
pitched | gabled | Synonym |
lean_to, monopitch, shed | skillion | Synonyms |
gabled_height_moved, gabled_irregular | saltbox | Uneven gable; no OSM tag says where the ridge sits, so a fixed offset is used |
double_saltbox, quadruple_saltbox | mansard | Close, not exact |
No roof (the building keeps its flat extrusion)
roof_shape | Why |
|---|---|
flat | Already right: the extrusion's top is the roof |
many, mixed, mix, multi | Discouraged in OSM; such buildings are normally drawn by their building:parts |
gabled_row | Undefined in OSM |
| anything else, or missing | Unknown values (including typos like 2 faces (pitched)) are ignored |
Colours
roof_color/facade_coloraccept#rgb,#rrggbb, CSS colour names (red,darkslategray, …), andrgb()/hsl(). Named colours are parsed literally (redis#ff0000).Materials pick a colour when no colour is set (palette from OSM Buildings):
Material (aliases) Colour roof_tiles(tile,tiles,rooftiles)#f08060brick(bricks)#cc7755slate(slates)#666666tar_paper(asphalt,bitumen,tar,roofingfelt,shingle,shingles)#333333metal(steel)#aaaaaacopper#a0e0d0concrete,plaster(plastered)#999999stone(block,masonry,granite,sandstone,paving_stones)#996666glass(glas,glassfront)#e8f8f8wood#deb887plants(grass,thatch)#009933canvas(sheet,sheets,tent),panel(panels)#fff8f0bronze/silver/gold#ffeecc/#cccccc/#ffcc00Defaults: roofs
#b9a99a; walls and gable ends use the layer'sgableColor(#d9d4ce).Facade colours (tagged or from a material) are toned down to 60 % saturation and a 30–88 % lightness range, the same on gable ends and extruded walls. Untagged walls keep the style's colour.
Roof faces are toned down as OSM Buildings does: every roof colour (tagged, from a material, or the default) is drawn at 70 % of its HSL saturation, so
redbecomes a brick red. Each building's roof lightness also shifts by ±0.03 or ±0.06 (stable for its feature id), so rows of identical roofs stay distinguishable. Wall-coloured faces (gable ends, glazing) are left as tagged, so they keep matching the extrusion walls.
Getting roof data
Overture's official tiles
Each Overture release publishes worldwide building tiles (PMTiles, zooms 5–14) with exactly the attributes above and numeric feature ids, buildings and building parts in separate source layers (building, building_part): give RoofsLayer one wall layer per source layer (see Roof shapes). For your own hosting, cut a region with pmtiles extract:
pmtiles extract https://overturemaps-extras-us-west-2.s3.amazonaws.com/tiles/2026-09-23.1/buildings.pmtiles \
paris.pmtiles --bbox=2.25,48.81,2.42,48.91Overture limits roof_shape to 14 values (dome, flat, gabled, gambrel, half_hipped, hipped, mansard, onion, pyramidal, round, saltbox, sawtooth, skillion, spherical), so OSM-only shapes such as side_hipped, butterfly, crosspitched or hipped-and-gabled arrive as one of these or not at all, and there is no roof_angle.
Your own source
Any source works if it carries the attributes above under these names, or under its own names mapped with fields. A source straight from OSM tags, for example:
new RoofsLayer({
id: 'roofs',
source: 'osm-buildings',
sourceLayer: 'building',
extrusionLayer: 'osm-buildings-3d',
fields: {
roof_shape: 'roof:shape',
roof_height: 'roof:height',
roof_angle: 'roof:angle',
roof_direction: 'roof:direction',
roof_orientation: 'roof:orientation',
roof_color: 'roof:colour',
roof_material: 'roof:material',
facade_color: 'building:colour',
facade_material: 'building:material',
},
});height must still be in metres and include the roof, and has_parts must be computed (OSM has no such tag).
Sources
- OSM wiki: Key:roof:shape
- OSM wiki: Simple 3D Buildings
- Overture building schema
- Overture
roof_shapevalues - Dome and onion profiles and the material palette: OSM Buildings (BSD-2-Clause)