# V5 street and environmental materials

Runtime deliverables are `street-materials.js` and `environment-materials.js`. Both are original code. The street maps are generated once at runtime and require no downloaded texture files. The supplied PNGs are inspection previews only.

## Integration

Copy `street-materials.js` and `environment-materials.js` beside the current `main.js`. Keep the current environment/presentation integration and its current versioned imports. The environmental module exports the same two functions as v4.

Add this import to `main.js` with the same cache version convention as the other v5 imports:

```js
import {applyStreetMaterials} from './street-materials.js?v=5';
```

After `buildArchitecture(...)` and any separately tagged forecourt construction:

```js
const streetSurfaces=applyStreetMaterials(THREE,{scene,renderer});
```

The architecture agent already added `street/adoquines`, `street/sidewalks` and `street/squares` names. The helper replaces only meshes with these prefixes, the optional mapped asphalt/concrete prefixes below, or an explicit `mesh.userData.streetSurface` value of `adoquines`, `sidewalk`, `plaza` or `asphalt`. It never selects buildings, roof tiles, fort masonry, water or unclassified terrain by color. A tagged forecourt needs the same metre-based world XZ UV convention as existing paving.

The helper returns counts, shared material/texture libraries, `restore()` and `dispose()`. A repeated call on the same scene returns the existing control. `dispose()` restores original mesh materials/shadow state and releases the replacement materials; cached textures are shared for the lifetime of the renderer.

For the lighting presets, call `streetSurfaces.setWetness(preset.wet ?? 0)`. Wetness clamps to 0–1 and defaults to 0; `getWetness()` reports its current value. All materials share the same uniform. Zero wetness leaves dry albedo, roughness and reflection strength identical. At positive wetness, broad irregular patches lower roughness toward 32% of its dry value with a minimum of 0.16, darken albedo by at most 20%, and gradually raise environment reflection intensity to 1. No water geometry, flooding, rainfall or new mask is added. The damp variation uses one additional noise evaluation only when the preset enables wetness.

## Explicit mapped asphalt/concrete

Apply `architecture-with-road-surfaces.patch` to the current `architecture.js`, or run the guarded transform:

```sh
python3 /private/tmp/isla-v5-assets/patch-road-surfaces.py INPUT_ARCHITECTURE OUTPUT_ARCHITECTURE
```

The script requires four exact anchors and rejects an already installed split. It routes explicit OSM `surface=asphalt` into `street/asphalt`, and `concrete`, `concrete:plates`, or `concrete:lanes` into `street/stone-footway`. The current data contains 122 asphalt-tagged and 64 concrete-tagged highway ways before existing land/building filters. Unknown, sett, cobblestone and other tags retain their existing paving coverage. No boundary, width, lift, subdivision, position, UV, collision or traversal calculation changes. Both new batches remain in the existing ground-height sampler.

This split adds 29 small material batches across the full scene, no triangles and no geometry-attribute bytes. Measured extra visible draws in the five existing benchmark views range from 2 to 21. The material-only helper by itself adds zero draws.

## Appearance and scale

| Surface | Generated maps | Repeating area | Interpreted block dimensions |
| --- | --- | --- | --- |
| Adoquines | 1024² color, normal, packed AO/roughness | 4.4 × 4.4 m | 22 × 11 cm |
| Sidewalk/concrete | 512² color, normal, packed AO/roughness | 2.4 × 2.4 m | 60 × 40 cm |
| Plaza | 512² color, normal, packed AO/roughness | 2.7 × 2.7 m | 45 × 45 cm |
| Asphalt | 256² color, normal, packed AO/roughness | 2.4 × 2.4 m | fine irregular aggregate |

Dimensions are visual interpretations, not surveyed brick/slab measurements. Adoquines have flat faces, chipped short chamfers, narrow joints, small pores, occasional hairline cracks, and mixed muted blue/gray/pale worn faces. Normal-only relief is 6.5 mm on adoquines and 2.2 mm on slabs; no displacement changes the walking surface. The materials disable legacy batch vertex colors, preventing the old brown concrete tint and double blue road tint. Broad low-contrast nonperiodic weathering reduces repetition. Maps use sRGB color, linear normals/roughness, mipmaps and anisotropic filtering capped at 8. Tangent normals are generated from the same height field as the joints. No large round cobble geometry is introduced.

All four map sets occupy approximately 25 MiB including mipmaps. Generation plus the complete CPU/material validation took about 0.6 seconds on this machine. Street materials use the standard Three PBR shader plus two inexpensive broad noise samples. Packed AO is available in the red map channel; the standard material currently consumes roughness from green, avoiding another texture fetch/UV channel solely for AO.

## Environmental delta from v4.4

Water adds one rotated, texture-driven capillary layer that fades between 24 and 150 m, slight irregular advection between existing scales, and screen-footprint filtering of sharp sun glints. There are still no analytic sine/cosine waves, no invented shallows or sandbars, and no displaced coastline. Distant normal attenuation and Fresnel remain. Reflection texture size remains the existing 512 setting; the API, sun/time uniforms and every-third-beauty-pass cadence are unchanged. `scene.overrideMaterial` passes still skip reflection capture so SSAO normals cannot contaminate the reflection.

Known hard ground receives a neutral gray stone tint rather than the previous brown tint. All OSM mask geometry/coverage, actual terrain vertices, grass/rock classification, far orthophoto, and v4 near-camera baked-shadow recovery remain unchanged. The reserved GLSL `patch` identifier remains absent (`lawnVariation` is retained).

## Visual references and provenance

- [Eric Pancer, Old San Juan's Blue Brick Roads I, 25 December 2010](https://commons.wikimedia.org/wiki/File:Old_San_Juan%27s_Blue_Brick_Roads_I.jpg), [original Flickr photograph](https://www.flickr.com/photos/vxla/5302631854/), [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/). The inspected close photograph informed rectangular proportions, narrow dusty joints, mixed blue/gray faces and pale worn tops. Research copy is `references/adoquines-eric-pancer.jpg` (4288 × 2848). No photo pixels are reused in the generated maps.
- [Daderot, Catedral de San Juan Bautista exterior, 21 October 2011](https://commons.wikimedia.org/wiki/File:Catedral_de_San_Juan_Bautista_de_Puerto_Rico_-_DSC06869.JPG), public domain. The inspected actual photograph supports restrained neutral gray ground around the cathedral; it does not establish numerical slab dimensions. Research copy was already present in v4 assets.
- [Discover Puerto Rico, Explore Puerto Rico's Architectural Gems](https://www.discoverpuertorico.com/article/explore-puerto-ricos-architectural-gems), official tourism site, identifies the characteristic blue-gray street paving. Used as contextual corroboration, not as a texture source.
- Existing road surface tags and terrain classification remain [OpenStreetMap contributors, ODbL](https://www.openstreetmap.org/copyright). No new polygons were invented for this revision.
- Existing water normal texture remains the Three.js example asset already in the project; no new externally sourced runtime images were added here.

## Validation

`validate-street-materials.mjs` passes using the installed actual Three module: deterministic maps, finite unit normals, color spaces, physical repeats, mipmaps, anisotropy, roughness, material sharing, named/tagged mesh isolation, unchanged geometry/UV arrays, idempotency and restoration, and expansion of every shader include. It validates the shared clamped wetness uniform, unchanged dry values and the 20% darkening/0.16 roughness bounds. It also writes the preview map pixels. `STREET-MATERIALS-V5-VALIDATION.json` records checks and hashes.

`validate-road-surfaces.mjs` builds both complete original and split architecture against the actual terrain and OSM data. `ROAD-SURFACES-V5-VALIDATION.json` confirms identical 702,324 paving triangles, all 254 sampled paving heights, 424 collision cells, building records, anchors, overall geometry counts/attribute bytes and bounds. The streaming geometry hash changes because identical triangles are grouped by different materials.

`validate-environment.mjs` passes actual Three shader-chunk expansion and all prior regression checks: mask coordinate frame, near shadow recovery, far/grass/rock preservation, no periodic analytic ocean bands, reflection override filtering, eye updates, installation and restoration. It verifies capillary fade and footprint-filtered glitter hooks. `environment-validation.json` records the result.

The previews were inspected for brick shape, color variation, joint/normal alignment and low relief. Root owns final browser/GPU inspection; these CPU checks do not claim an actual render test.
