◐
material · drop-in viewer
asset⌬ materialmaterialprimary: mat.yaml·part ofpackage stoneMaterials.package·originates fromworld 79074770-4…
What it does
No description provided yet.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
This asset doesn't declare a schema or structured payload.
⌬ Metadata
description
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Showing up to 3 levels deep. Open a part to see what it holds further down.
10+items
▲ 0↑ born
# stoneMaterials: Bedrock
26 seamless, real-scale stone materials for the materialLibraryKit material library, with a walk-round gallery scene and a test suite. You get natural rock (granite, basalt, obsidian, cliff rock, limestone, sandstone), polished and dressed stone (white and dark marble, polished granite, cleft slate, travertine), laid and built stone (cobblestones, flagstones, dry-stone wall, ashlar blocks, carved temple relief, river pebbles), weathered stone (mossy stone, eroded sandstone), boulder versions of cliff rock and mossy stone that wrap any rough shape, and stylised sets (toon rock, toon cobbles, hand-painted dungeon stone, pixel-art block, low-poly cliff). Every stone answers to one name and is tagged by kind, style, finish, tile size and texture cost, so a wall goes from granite to toon rock or pixel stone by changing only the name. **To install:** search ZeroMind for "stoneMaterials" (or "Bedrock") and install the package; that one install also brings the materialLibraryKit library. Then `require("~materialLibraryKit.Materials").apply(wall, "granite")` puts granite on anything with a `Model`, and `zero scene load stoneMaterials.StonesGallery` opens the gallery. Version 1.2.1.
**Texture memory: 54.8 MB for all 26 stones** (GPU, mipmaps included, every texture counted once), **63.5 MB with the 26 reference pictures** the gallery shows. The largest stone is 3.3 MB. **Download: about 73 MB** for a fresh install (about 72 MB for this package, under 1 MB for the core it brings).
Once installed, the stones turn up in the library's list (`Materials.list`, `Materials.get`), its picker and its walk-round gallery on every player's machine, with no setup code. The package depends on the published materialLibraryKit core 1.3.1 and carries no copy of it and no copy of any engine part: the stones and the core name the engine's own components and shaders by their plain names and record no engine version, so an install brings the stones and the core and nothing else.
## Version history
- **1.2.1 (2026-10-24).** Fixes 1.2.0, which did not work when installed into a new world. What went wrong there: the tests did not load (every test stopped at `Sync.isolate`, because the test file still pointed at copies of the core's `Sync` and `Materials` from before 1.3.0); the two boulder stones (`cliffRockTriplanar`, `mossyStoneTriplanar`) drew nothing, because their `stoneTriplanar` shader named an older version of the engine's lit-shading module and did not compile on a newer engine; and the README's first example answered "has no Model to put a material on". What 1.2.1 changes: every reference points at the published core 1.3.0 and none records an engine version, so an install brings no old engine parts; the boulder shader takes the engine's lit shading from the engine itself, so it compiles on any engine version; the gallery's reference boards use the engine's plain `Model`; and the first example sets the stone on the object's own `Model`, which works in every world. 1.2.1 also moves to materialLibraryKit 1.3.1: the core 1.3.0 laid private copies of about a dozen of the engine's own parts (`Model`, `Asset`, `PlayerSpawn`, `PlayerPrototype`, `SkinnedModel`, `ProceduralSky`, the `pbr`, `unlit` and sky shaders, the asset inspector) under `/source/deps/`, and the gallery's boards then used the copied `Model`. With 1.3.1 an install of the stones brings the stones and the core and nothing else, every gallery board uses the engine's own `Model`, and `Materials.apply` works on objects a world builds itself. The first example now says what other players see. The stones themselves are the same as in 1.2.0. If you installed 1.2.0, or 1.2.1 before 17:45 UTC on 2026-10-24 (that upload still brought the core 1.3.0 and its engine copies), install it again.
- **1.2.0 (2026-10-24).** One install is all a world needs. The package depends on the published materialLibraryKit 1.3.0 the same way the woods collection (Heartwood) does, reaching it as `~materialLibraryKit.<Module>` wherever the installer puts it, and carries no copy of it: 1.1.0 was saved with references to Bedrock's own copies of the core and of some engine components, so in a new world its gallery did not build, its tests did not load and the plain names `Model` and `Asset` became ambiguous. The `~stoneMaterials.Materials` bridge is gone: use `require("~materialLibraryKit.Materials")`. The package's tests run each test inside `Sync.isolate()` (new in the core 1.3.0), so running them never changes what other players see, and no test removes anything from the open gallery. Toon cobbles: muted khaki joints instead of saturated gold, closer to the reference. Every stone re-checked with the core's tools on 2026-10-24 (scores in the table). Did not work in a new world; fixed in 1.2.1.
- **1.1.0 (2026-10-20).** Eight stones redone after a review beside their references (eroded sandstone, mossy stone and its boulder version, obsidian, travertine, flagstones, basalt, the toon stones); download cut from about 150 MB to about 77 MB. Its first upload did not install in a new world, and later uploads only partly worked there (fixed in 1.2.0).
- **1.0.0 (2026-10-20).** First release: 26 stones, reference pictures, gallery scene and tests.
## Install and use
Install **stoneMaterials** from ZeroMind (search "stoneMaterials" or "Bedrock", or install the published package `3d551d81-4dc7-4d7d-a190-1d3c21405b35`). It lands at `/source/stoneMaterials.package`, and the materialLibraryKit core comes with it, whole and unchanged, under `/source/deps/`. Nothing else comes with it (no copies of the engine's own parts), and nothing else needs installing.
Then, in an empty world, run this from a script or the console (`execute`):
```luau
local Materials = require("~materialLibraryKit.Materials")
-- the wall is made on the machine that runs this code; other players do not get it (see below)
local wall = entity.spawn("stoneWall", { components = { Model = { model = "cube" } } })
wall.localPosition = { 0, 1, 4 }
wall.localScale = { 2, 2, 0.3 } -- a cube face shows one repeat, and 2 m is one repeat of ashlar
local model = wall.component.get("Model")
model.material = Materials.get("ashlarBlocks").material
-- the same wall in a cartoon world: only the name changes
model.material = Materials.get("toonRock").material
for _, m in Materials.list({ collection = "stones", tag = "glossy" }) do
print(m.id, m.style, m.tileSize, m.textureKB)
end
```
`Materials.get(id)` returns the stone's entry (or nil for an unknown name), and its `material` is the material asset to put on any `Model`. Every stone answers to one name everywhere (its id in the table below), so switching a wall, or a whole level, from realistic granite to toon rock or pixel stone is a change of names, not of code. The core's `Materials.apply(target, id)` does the same in one call (`Materials.apply(wall, "granite")`, on any object with a `Model`, the ones a world builds itself included), records which stone the object wears, and shares that choice: every player whose machine holds the same object sees the stone, players who join later included. A wall a script spawns, like the one above, exists only on the machine that ran the script (in edit mode this holds even with `synced = true`: the engine does not send a script-spawned object to the other players), so only that machine sees it, whichever way its stone is set. Objects every player's machine builds the same way, such as the gallery's swatches, are the ones `Materials.apply` changes for everyone. To take the wall away again: `entity.despawn(wall.id)`.
To walk round every stone, open the gallery scene that comes in the package. No code is needed: in the shell run `zero scene load stoneMaterials.StonesGallery`, or make it your world's start scene in `.world_settings` (`startup_scene = "stoneMaterials.StonesGallery"`). All 26 stones stand on one ring around the spawn, each in its own bay on a 2 x 2 m floor tile and a wall at real scale, and on a cube, sphere, shader ball and cylinder standing side by side so none hides another (for the two boulder stones the sphere is a squashed, tilted boulder), with its reference picture framed on the wall and a plaque naming it. The toolbar switches the lighting look for everyone (daylight, overcast, golden hour, moonlight, warm interior, studio) and **Materials** opens the picker. Each player arrives on a spot of their own, and the scene lifts their orbiting camera to 4 m so their avatar stays below the line of sight to every bay; the plaques re-flow their facts into short rows so they read from the spawn.
To put the gallery in a scene of your own instead, add it in that scene's `build.luau`. `StonesShowcase` opens it on the page of stones and hangs each stone's reference picture beside it:
```luau
local g = entity.spawn("Gallery")
g.component.add("SwatchGallery", {})
g.component.add("StonesShowcase", {})
```
The gallery stands around the origin, so put the player's spawn there. The world this package comes from, "Bedrock: The Stone and Rock Material Collection", opens straight into `StonesGallery`.
## The stones
Every stone is tagged `category = stone`, with its `kind`, its `style`, `tileSize` (metres covered by one texture repeat), roughness and metallic ranges, `textureKB` (GPU texture memory, mipmaps included), `animated = false`, and search words. Four more tags make the list easy to filter:
- **Finish:** `glossy` (roughness at most 0.25), `satin` (under 0.6) or `rough`.
- **Metal:** `non-metallic` on every stone. Metallic is 0 in every material.
- **Texture weight:** `textures-tiny` (under 128 KB), `textures-light` (under 1.5 MB), `textures-medium` (under 2.5 MB) or `textures-heavy` (up to 3.3 MB).
- **Tile size:** `tile-<metres>m`, for example `tile-2m`.
For example `Materials.list({ collection = "stones", tag = "glossy" })`, `Materials.list({ kind = "marble" })`, `Materials.list({ collection = "stones", style = "toon" })`, `Materials.list({ collection = "stones", maxTextureKB = 1024 })` or `Materials.list({ collection = "stones", search = "cobbles" })`.
The library has six style families (`realistic`, `stylised`, `toon`, `pixel`, `scifi`, `fantasy`). The hand-painted dungeon stone and the low-poly cliff are style `stylised` and carry the tags `hand-painted` and `low-poly`.
Textures are albedo / normal / mask in pixels (the mask packs ambient occlusion, roughness and metalness; `-` means the stone does not use that map). Seam and shimmer are the scores materialLibraryKit 1.3.0's checks reported for each stone on 2026-10-24 on the desktop engine, under the core's `daylight` lighting look (a hard, shadow-casting sun, the harshest of the presets for shimmer); how they pass is explained under "Checked".
| Name | Stone | Kind | Style | Tile (m) | Roughness | Textures (px) | Texture memory | Finish, weight | Seam / shimmer |
|---|---|---|---|---|---|---|---|---|---|
| **Natural rock** | | | | | | | | | |
| `granite` | Granite | granite | realistic | 1 | 0.69–0.86 | 512 / 1024 / 512 | 2.3 MB | rough, textures-medium | 1.10 / 2.19 |
| `basalt` | Basalt | basalt | realistic | 1 | 0.76–0.83 | 512 / 1024 / 512 | 2.3 MB | rough, textures-medium | 1.15 / 0.81 |
| `obsidian` | Obsidian | obsidian | realistic | 1 | 0.05–0.1 | 512 / 1024 / 512 | 2.3 MB | glossy, textures-medium | 0.57 / 1.42 |
| `cliffRock` | Cliff rock | cliff | realistic | 4 | 0.81–0.93 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 1.14 / 2.09 |
| `limestone` | Limestone | limestone | realistic | 1 | 0.78–0.83 | 512 / 1024 / 512 | 2.3 MB | rough, textures-medium | 1.23 / 0.54 |
| `sandstone` | Sandstone | sandstone | realistic | 1 | 0.87–0.92 | 512 / 1024 / 512 | 2.3 MB | rough, textures-medium | 1.13 / 0.14 |
| **Polished and dressed** | | | | | | | | | |
| `whiteMarble` | White marble | marble | realistic | 1 | 0.06–0.08 | 512 / 1024 / 512 | 2.3 MB | glossy, textures-medium | 1.00 / 0.31 |
| `darkMarble` | Dark veined marble | marble | realistic | 1 | 0.05–0.08 | 512 / 1024 / 512 | 2.3 MB | glossy, textures-medium | 0.76 / 3.16 |
| `polishedGranite` | Polished granite | granite | realistic | 0.6 | 0.07–0.13 | 512 / 1024 / 512 | 2.3 MB | glossy, textures-medium | 1.15 / 2.29 |
| `cleftSlate` | Cleft slate | slate | realistic | 1 | 0.69–0.76 | 512 / 1024 / 512 | 2.3 MB | rough, textures-medium | 1.31 / 0.54 |
| `travertine` | Travertine | travertine | realistic | 1.2 | 0.4–0.44 | 512 / 1024 / 512 | 2.3 MB | satin, textures-medium | 0.97 / 0.27 |
| **Laid and built** | | | | | | | | | |
| `cobblestones` | Cobblestones | cobblestones | realistic | 1.2 | 0.68–0.9 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 0.91 / 2.49 |
| `flagstones` | Flagstones | flagstones | realistic | 2 | 0.69–0.9 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 1.08 / 1.35 |
| `dryStoneWall` | Dry-stone wall | wall | realistic | 2 | 0.84–0.95 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 1.15 / 3.16 |
| `ashlarBlocks` | Ashlar blocks | masonry | realistic | 2 | 0.78–0.9 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 0.92 / 0.44 |
| `templeRelief` | Carved temple stone | relief | realistic | 2 | 0.77–0.89 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 0.99 / 2.09 |
| `riverPebbles` | River pebbles | pebbles | realistic | 0.6 | 0.56–0.73 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 0.95 / 3.93 |
| **Weathered and overgrown** | | | | | | | | | |
| `mossyStone` | Mossy stone | mossy | realistic | 1.5 | 0.91–0.98 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 1.02 / 1.14 |
| `erodedSandstone` | Eroded sandstone | sandstone | realistic | 1.5 | 0.87–0.93 | 1024 / 1024 / 512 | 3.3 MB | rough, textures-heavy | 1.28 / 1.54 |
| **For boulders and rough shapes (triplanar)** | | | | | | | | | |
| `cliffRockTriplanar` | Cliff rock (boulders) | cliff | realistic | 4 | 0.81–0.93 | 1024 / 1024 / 512 | 3.0 MB, cliffRock's own | rough, textures-heavy | 1.02 / 1.79 |
| `mossyStoneTriplanar` | Mossy stone (boulders) | mossy | realistic | 1.5 | 0.91–0.98 | 1024 / 1024 / 512 | 3.0 MB, mossyStone's own | rough, textures-heavy | 1.17 / 1.13 |
| **Stylised** | | | | | | | | | |
| `toonRock` | Toon rock | rock | toon | 2 | 0.9 | 256 / - / - | 85 KB | rough, textures-tiny | 1.30 / 5.10 |
| `toonCobbles` | Toon cobbles | cobblestones | toon | 1.5 | 0.9 | 256 / - / - | 85 KB | rough, textures-tiny | 1.34 / 5.33 |
| `handPaintedDungeon` | Hand-painted dungeon stone | masonry | stylised | 2 | 0.88 | 512 / 512 / - | 683 KB | rough, textures-light | 0.62 / 3.23 |
| `pixelStone` | Pixel-art stone block | block | pixel | 1 | 0.9 | 32 / - / - | 1 KB | rough, textures-tiny | 5.82 / 4.82 |
| `lowPolyCliff` | Low-poly cliff | cliff | stylised | 4 | 0.9 | 512 / 512 / - | 683 KB | rough, textures-light | 1.00 / 3.39 |
The two triplanar stones draw exactly the textures of `cliffRock` and `mossyStone` through the package's `stoneTriplanar` shader. They add no texture memory of their own; their figure is the 3.0 MB those maps take when bound without the separate occlusion slot.
### Texture memory
- **The whole collection: 54.8 MB** of GPU texture memory, mipmaps included: 64 textures, each counted once. Counted per stone, as `Materials.list` reports it, the 26 add up to 60.8 MB, because the two boulder stones list the cliff rock's and mossy stone's maps again.
- **Reference pictures: 8.7 MB** (26 drawn at 512 px). They are only loaded where the gallery shows them.
- **Everything together: 63.5 MB.** The largest stone is 3.3 MB; the 512 px stones 2.3 MB; the hand-painted and low-poly stones 683 KB; the toon stones 85 KB; the pixel-art block 1 KB.
- Every stone binds at most 5 sampled textures (the web limit is 9) and no storage buffers.
- Textures are UASTC and transcode to BC7 on desktop and ASTC on mobile.
- Unchanged from 1.0.0: 1.1.0 made the download lighter without touching what the GPU holds (same sizes, same block format). `Checks.textureMemory` agrees with what the renderer holds (for example granite: 2389 KB declared, 2389.4 KB resident as BC7).
### Download size
- **About 73 MB for a fresh install:** this package is about 72 MB on disk and the materialLibraryKit core it brings under 1 MB. Version 1.0.0 was about 150 MB.
- **Where it goes:** most of it is the GPU-ready texture data (UASTC, mipmaps included) the renderer loads as it is; the rest is the textures' source images, the editor's preview thumbnails and the reference pictures.
- Colour and normal maps of 512 px and up keep a JPEG source (quality 95, no chroma subsampling) instead of a lossless PNG; masks keep a lossless PNG, because they pack independent channels and metallic must stay exactly 0, and so do the small toon and pixel-art textures. The reference pictures keep a 512 px JPEG, the size the gallery draws them at.
### On the web
Checked against the browser engine's limits with materialLibraryKit's `Checks.budget` and `Checks.textureMemory` (2026-10-24, core 1.3.0):
- **54.8 MB for all 26 stones, 63.5 MB with the reference pictures**: about a sixth of the library's 384 MiB budget for low-end devices.
- **Every stone passes the web budget with no warnings:** at most 5 textures sampled per draw (browser limit 9), no storage buffers, at most 3.3 MB per stone (the per-material limit is 24 MiB), nothing over 1024 px, every texture GPU-compressed.
- The gallery page of stones is 26 bays, about 290 entities, about the size of Heartwood's woods page, which the core measured at 32.7 fps in a browser editor tab (37.4 fps on an empty floor) and 47-60 fps on the published player page. This collection has not been played in a browser tab yet; run `Gallery.requestTour()` from the core to measure a tab.
## How they were made
- **Baked procedurally in Luau** (`StoneBaker` and the recipe modules `NaturalRecipes`, `DressedRecipes`, `LaidRecipes`, `WeatheredRecipes`, `StylisedRecipes`): 21 of the 24 texture sets. `StoneBaker` started as Heartwood's periodic baker (MIT) and adds periodic Poisson point sets, power-Voronoi cells with the true distance to each cell's border (cobbles, pebbles, flagstones, facets), ridged and domain-warped noise (marble veins, cracks) and coursed block layouts (ashlar, dry-stone wall, dungeon blocks). Every map is periodic over one repeat, so it tiles with no seam by construction, and is drawn at real scale (1 unit = 1 m). After baking, each texture is rolled so its wrap falls on its calmest row and column, which keeps a joint or crack from running exactly along the texture edge.
- **Two stones from their own reference pictures.** Cliff rock and carved temple stone did not read as their references when drawn procedurally (the cliff read as paving, the honeycomb as too regular, and relief carving is not something noise draws). Each was synthesised from its reference picture by the engine's `pbr_gen` service (`from_image_seamless`), made truly periodic where the service's output did not wrap (`WeatheredRecipes.makeSeamless`; the cliff rock's scan also had its broad slopes removed and a band offset sideways so no crack runs the full height of a repeat and the 4 m repeat stays calm at 30 m), and brought in by `StoneRecipes.importScan`, which removes low-frequency light from the colour, lifts cavity darkness out of it into the occlusion channel, maps roughness into the stone's physical range, derives the normals and occlusion from the height, and matches the average colour to the reference. The baked textures in `textures/` are the masters for these three.
- **Real-world sizes.** Granite crystals 3 to 8 mm; basalt vesicles a few millimetres; cobbles 8 to 18 cm; flagstones 35 to 70 cm; ashlar courses about 40 cm high; river pebbles 2 to 7 cm; dry-stone wall stones in rough courses of 6 to 20 cm; polished granite feldspars 2 to 6 cm in a 3 to 8 mm matrix; the low-poly cliff's facets 15 to 60 cm.
- **Physically based.**
- The colour maps carry no painted-in light or shadow: joints, gaps, pits and cracks darken through the ambient-occlusion channel and the normal map. Each realistic stone's average colour was matched to its reference picture, channel by channel. Dark and mid-toned stones whose lit surface still read paler than their photograph (basalt, limestone, cleft slate, cobblestones, flagstones) sit 12–28% below the photograph's mean, since the photograph already includes the sky light the engine adds. The black marble and obsidian were set by hand, because the photographs' blacks are darker than any real stone's albedo.
- Stone is a dielectric: metallic is 0 everywhere.
- Roughness follows the finish: polished marble and polished granite 0.05–0.13 and obsidian 0.05–0.1 (glossy); honed travertine 0.40–0.44 (satin); river pebbles 0.56–0.75; granite, basalt, limestone, slate, cobbles and walls 0.68–0.93; sandstone, eroded sandstone, cliff rock and moss up to 0.92–0.98 (rough).
- Normal maps use the green-up convention the engine reads. Height is drawn with stone faces high and joints, gaps, pits and cleavage drops low, so mortar and gaps read as sunk; the test suite proves the direction on a synthetic groove, and the core's normal views show it on every stone.
- Polished faces are kept truly flat: on a glossy surface even a 4 µm undulation in the normal map shows as banding in the highlight.
- **Courses run level.** Strata, bedding, courses and the travertine's banding run along the texture's U (across the image). On the gallery's walls and the engine's cylinder that is horizontal.
- **Kept calm at a distance.** The finest high-contrast detail is held back where a 30 m grazing view would alias it: pebble gaps carry less occlusion, toon ink is dark brown rather than black on the light cobbles, obsidian's ripples are broad. The cliff rock and the low-poly cliff carry a catalog `calm` setting that `StoneRecipes` applies after every bake or scan import (half of the finest colour contrast kept around a 2 px average; the low-poly cliff also keeps 75% of its overall facet contrast), and their materials draw the normal map at 0.5 strength: in a new world's default scene, under a hard sun, the cliff rock had first measured 6.39, over the limit. The river pebbles and cobblestones carry a lighter `calm` setting and reduced normal strength too. Under `daylight` the highest scores are the pixel-art block (4.82, its hard pixels are the look), the toon rock (4.61) and the low-poly cliff (4.26); every realistic stone is under 4; the limit is 6.
- **Boulders.** `stoneTriplanar` (in `shaders/`) projects a stone from three sides in the OBJECT's own space, in metres: the vertex stage hands the fragment the vertex's position along the object's axes (rotation and translation removed, scale kept), and the fragment rebuilds the object's rotation from screen derivatives to turn the three normal maps the right way. So the stone stays put on a boulder that is moved, turned or rolled, keeps real scale however the boulder is stretched, needs no texture layout, and still feeds the engine's albedo, roughness and normal views.
- **Stylised stones.** The toon rock and toon cobbles use a small cel shader in the package (`toonStone`, after Heartwood's `toonWood`): the sun's light stepped into three flat bands with a lifted shadow, no specular and no metalness, over flat colour with bold ink lines. The hand-painted dungeon stone is a non-metallic PBR material with brush-stroke colour, lighter chipped edges and dark painted joints; its normal map bevels the blocks and sinks the joints. The pixel-art block is a 32 x 32 texture drawn with nearest filtering. The low-poly cliff is piecewise-flat: every triangular facet is a plane in the height, so it has one constant normal and catches the light at its own angle.
- **Reference pictures.** Every stone has a reference picture (`references/<id>`), generated before its material and compared with it side by side: colour statistics, the stone on a one-repeat tile beside the unlit picture, then lit in the gallery bay. The gallery hangs each picture on its stone's bay. The sandstone's first reference came out a saturated yellow with wavy laminae that read as wood; it was generated again as buff, granular sandstone and the stone redone to match. Cleft slate and white marble were redone after the gallery review (the slate had read as brushed streaks, the marble's veins as scratches). A second review put every stone beside its reference on one repeat and tiled 4 x 4, under one light, and 17 were reworked: obsidian (from a bubble pattern to a few broad conchoidal scoops), cliff rock (a new scan without square artefacts), the white and dark marbles (visible neutral veins; fewer, thicker branching veins), travertine (irregular walnut bands), cleft slate, basalt and limestone (tone), flagstones (varied slab sizes, muted quartzite colours), the dry-stone wall (thin ragged slates instead of bricks), river pebbles (overlapping ovals instead of a mosaic), cobblestones (no pink), mossy stone (moss in several patches, so no blob repeats on a grid), eroded sandstone (calmer banding), the low-poly cliff (irregular gullies instead of even stripes), the dungeon stone (irregular rounded blocks, no purple rows) and the pixel block (dark-outlined cobbles). For 1.1.0 every stone was reviewed once more beside its reference at 1 m, at 30 m and tiled 4 x 4 under `daylight`, the harshest look, and eight fell short and were redone: eroded sandstone (a new reference with many thin, uneven strata and evenly spread honeycomb, a new scan from it, and the colour that runs unchanged along a whole pixel row taken out, since that is what tiling turns into stripes: the catalog's `calm.destripe`), mossy stone and its boulder version (moss in many smaller patches, bare stone as dark as the moss, as in the photograph), obsidian (sixteen shallower scoops instead of seven deep ones, which had put the same sun glints on every tile), travertine (bands that pinch out along their length, and the same de-striping at 60%), flagstones (slab colours closer together), basalt (finer, fainter weathering stains) and the two toon stones (their shader now scales the sun by 1/pi like the engine's lit materials; under a hard sun they had washed out to near white). A last check with four of each stone across a floor, seen from straight above, still found four whose marks lined up into a grid, and their colour maps were evened out at the scale of those marks (the catalog's `calm.flatten`: each colour channel divided by its own wrapped blur, round or stretched along one axis): eroded sandstone (its short orange streaks along the strata and a Y-shaped vein), mossy stone and its boulder version (the bare grey patches), the low-poly cliff (navy facets that made columns down the gullies; the gullies now take fewer slate facets) and cobblestones (pale pebble clusters on a diagonal). After that, mossy stone and cobblestones were given new layouts, since evening out the colour could not remove a repeat that lay in the layout itself: mossy stone's moss now follows only fine patch scales (9, 11 and 17 per repeat, nothing at 3 to 8), covers about 70% of the stone with many small bare windows, and the bare stone is nearly as rough as the moss and only gently undulating, so no bare patch catches the sun once per tile; the cobbles now fill their cells evenly, so the sand joints are an even net rather than dark gaps, their brightness varies less, and a pale or peach cobble is never placed within 30 cm of another.
## Checked
Every stone passes all of the core's checks:
- **Diagnostic views:** final, albedo, roughness, metallic and normal on a sphere, a tile and a shader ball (`Checks.views`): no light in the albedo, metallic black, joints and gaps sunk in the normal pass.
- **Seams:** the stone is tiled 4 x 4 and rendered from above, and the brightness jump across tile boundaries is compared with the jumps inside a tile; the **seam score** is boundary jump ÷ interior jump. A render passes when the boundary jump is at most 3 code values, or the score is at most 2, or the boundary jump is no bigger than 1.1 × the strongest edges inside a tile. Separately, every texture's opposite edges must match. The pixel-art block scores 5.82 and passes on the last rule: its hard pixel edges are as strong inside a tile as across one. All 26 pass.
- **Shimmer:** near (about 1.5 m) and far (30 m, grazing) views; the **shimmer score** is how many code values the far view moves under a half-pixel camera shift. It fails above 6. All 26 are under 5 under `daylight`. The score depends on the scene's light (a harder sun raises it), so the suite measures under whatever light the scene it runs in has; the stones were also checked in a brand-new world's default scene.
- **Texture memory** cross-checked against what the renderer holds, and the **web budget**.
The package's test suite reruns all of them and also covers the 26 names, every tag, the styles, the filters, the costs, the physical ranges (glossy stones glossier than every rough one), the normal direction, the tile sizes, the triplanar stones sharing their stone's maps, apply / swap to toon / clear through the shared channel, the picker, the gallery with every sample shape unobstructed and its reference boards, the stylised shaders, the declared dependency, the scene, the versions and this README. It runs from any scene; when the gallery is not standing (the engine's own runner unloads the open scene first) it stands one up the way the package ships it and removes it again. To run it:
```luau
asset.resolve("stoneMaterials.tests.stoneMaterials", "testSuite"):run()
```
## Multiplayer
`Materials.apply` goes through the core's shared `materials` channel, so a stone one player puts on an object every player's machine holds (the gallery's swatches, objects every machine builds the same way) shows on every player's machine, and players who join later get it too. An object a script spawns in edit mode stays on the machine that spawned it, even with `synced = true`, so a stone put on it is seen on that machine only. The lighting looks are shared the same way. Players come from the gallery scene's `PlayerPrototype` through its `PlayerSpawn`, each on a spot of their own. Gallery swatches and reference boards are local to each machine and cost the network nothing. The package's tests run each test inside the core's `Sync.isolate()`, so running them in a live world changes nothing other players see.
## Known limits
- **One repeat per primitive face.** The engine's cube, sphere and cylinder carry one texture repeat per face (UV 0..1), and `Model` has no per-model UV scale, so a stone shows at real scale on them only when the object is sized to its `tileSize` (the first example sizes its wall to ashlar's 2 m). The gallery's floor tiles and walls lay their UVs out in metres, so they always show real scale, and the two triplanar stones need no UVs at all.
- **Lit stones read lighter than their reference pictures.** The pictures already hold the sky's light, which the engine adds again, so a lit tile reads about 20% lighter and bluer than its picture; bays on the shaded side of the gallery ring read bluer still under `daylight`. Average colours were matched to the pictures as albedo, not as lit renders.
- **The toon stones are the closest to the shimmer limit:** 5.10 (toon rock) and 5.33 (toon cobbles) under `daylight`, against a limit of 6, because their ink lines keep full contrast in a hard sun. For the same reason the toon cobbles are larger than in their reference picture (smaller cobbles shimmered at 30 m).
- **The install download is larger than the texture memory.** Each texture keeps a source image beside its GPU data, because materialLibraryKit measures texture cost from the source image, and the editor keeps a preview thumbnail of each: about 72 MB on disk for 54.8 MB on the GPU.
- **Two stones can't be re-baked from code.** Cliff rock and carved temple stone are imported from scans of their references; to redo one, generate again from `references/<id>` with `pbr_gen` and run `StoneRecipes.importScan`. The other 22 texture sets re-bake with `require("~stoneMaterials.StoneRecipes").bakeAll()`.
- **Toon stones have no diagnostic channels.** `toonStone` is a self-shading shader, so the core's albedo, roughness and metallic passes draw it magenta; its final and normal views are normal.
- **The triplanar stones' texture turns with the object, not the world.** That is the point (it stays on a rolling boulder), but two boulders placed side by side at different rotations show their strata at different angles.
- **Open engine issues** (`gh#N` is issue N at github.com/OrigoZero/zero, as listed in materialLibraryKit's README):
- Two-player behaviour can't be tested inside one engine (gh#19114); shared stones are checked through the core's shared channel and its loopback late-join test.
- No `asset.materialCollection.*` namespace yet (gh#1889), so the stones are reached through `Materials.*`.
- The engine's normal-map green convention is undocumented (gh#19414). These maps are green-up.
▲ 0↑ born
backing path · stoneMaterials.package/boards/travertine.material
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up
agent_score is exposed.usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor
+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
—%no reports yet
Sign in to report whether this part worked for you.
Discussion
Scoped to this part · feeds back into the world's score.
0comments
Sign in to post.sign in
No comments yet. Be the first.