# Nyx and Reprise visual import

These are conversions of the authored CSS BSPs and their packed assets. No map
art was generated or reconstructed from video. Rendering and collision use the
same pinned sources; visual imports do not change movement or collision.

| Map | Author | BSP SHA-1 | Source bytes |
| --- | --- | --- | ---: |
| surf_nyx | Syncronyze | `152ead154b26241dff136a4e0903543ce5d223ed` | 89,494,692 |
| surf_reprise | TeMP | `0e826d0d34c17122c4713d3176bf212ba90381d8` | 41,906,532 |

Nyx's [original author page](https://gamebanana.com/mods/122639) also credits
ShadowSheep for optimization, fixes and sounds. It recommends HDR and at least
medium texture detail so the grid below the ramp glass remains visible. Its
listed licence is CC BY-NC-ND 4.0; the conversion does not grant broader
redistribution or commercial rights. Reprise's author is independently credited
in this [CSS KSF recording](https://www.youtube.com/watch?v=vxN4W9RgtDE). Original
map and stock CSS assets retain their owners' rights.

## Reproduction

Use the pinned download cache and a read-only installed CSS asset directory:

```text
python scripts/import_boreas_visuals.py node_modules/.map-imports/surf_nyx.bsp --slug nyx --map-id surf_nyx --author Syncronyze --game-dir "PATH/Counter-Strike Source" --texture-format lossless-webp --compressed-textures --invalid-skin-policy default
python scripts/import_boreas_visuals.py node_modules/.map-imports/surf_reprise.bsp --slug reprise --map-id surf_reprise --author TeMP --game-dir "PATH/Counter-Strike Source" --texture-format lossless-webp --compressed-textures
python scripts/validate_new_map_visuals.py --slugs nyx,reprise --game-dir "PATH/Counter-Strike Source"
python -m unittest discover -s tests -p test_nyx_reprise_visuals.py
```

`CAPTURE_MAPS=nyx,reprise npx tsx scripts/capture-new-map-previews.ts` uses the
actual browser renderer at port 4193, configurable through `UI_BASE_URL`. Optional
`CAPTURE_FRACTIONS` selects comma-separated normalized points in native telemetry.
The helper also captures each authored start. Positions/views are visual review
cameras, not commands or proof of playable routes.

## Export and asset verification

| Measure | Nyx | Reprise |
| --- | ---: | ---: |
| World faces | 2,629 | 25,363 |
| Displacement surfaces | 1,964 | 0 |
| World material batches | 91 | 103 |
| Authored sky portal faces | 0 | 548 |
| Static prop instances | 837 | 83 |
| Dynamic initial poses | 21 | 0 |
| Model/skin variants | 48 | 6 |
| All geometry batches | 293 | 112 |
| Decoded texture images | 414 | 236 |
| Native compressed textures | 39 | 20 |
| Decoded-path asset bytes before transport gzip | 26,982,419 | 16,282,812 |

The exact compiled black/ordinary materials survive the surface-flag filter.
Reprise's original sky portal faces use the depth-only pass established by the
Kitsune regression. Nyx is an enclosed cave with no compiled sky portals.
Neither map receives artificial room/stage hiding or invented visual walls.

All 650 texture images match their source decoded VTF pixels exactly. All 59
native DDS exports preserve original DXT blocks and mipmaps byte for byte. The
405 mesh batches have finite vertices, valid buffer lengths and in-range
triangle indices. Results are retained in
`fixtures/nyx-reprise-visuals/integrity.json`. These conversion checks share
decoders with import and are not an independent native-rendering comparison.

Nyx's native texture subset contains 14,652,232 bytes of mip data versus 88,391,736
bytes of equivalent RGBA mip data, an 83.4% saving. Reprise's corresponding figures
are 10,235,056 versus 56,711,824 bytes, an 82.0% saving. These are asset-derived
payload estimates, not measured total GPU/browser memory. Other textures,
geometry, render targets and JavaScript allocations are additional.

## Resolved format issues

- Reprise has three packed materials whose compiled BSP texture dimensions are
  zero: `test/color008`, `nightfall/track_centerpiece`, and `reprise/thanks`.
  Their original VTF headers provide 128×128, 1024×1024 and 1024×1024 dimensions.
  The importer uses those values for UV normalization and records the resolution
  in `textureDimensionsFromVtf`. It preserves every valid compiled dimension and
  fails explicitly if neither source provides usable dimensions.
- Reprise packs an MDL version 45 shrub model. Its used header, mesh and VVD fields
  retain the supported layout. The reader now accepts it; a regression compares
  exported positions directly with the original VVD and confirms all 30 authored
  instances and 1,180 model triangles are present. No substitute shrub was used.
- Nyx has exactly two out-of-range authored skin families: static props 829 and 830
  request 11/11 and 3/3. Both are non-solid decorative ramp props outside the main
  reviewed route. An explicit `--invalid-skin-policy default` option retains the
  original geometry using family 0 instead of omitting the props. The authored
  index, family count, rendered index and `nativeConfirmed:false` are recorded
  in `modelSkinFallbacks`, with visible import warnings. This fallback is a
  documented approximation; native CSS material selection for these two cases
  has not been confirmed. Default importer behavior still rejects invalid skins.

Four source/analytic regressions pass: dimension preservation/failure, pinned
zero-dimension VTF recovery, v45 source vertices/instances, and explicit Nyx
fallback scope/material-family selection. The previous maps were not regenerated.

## Browser review

Twenty start/route camera views loaded in Edge Chromium with no page or console
errors. Inspected Nyx views retain the blue grid under the glass, purple crystals,
cave walls and main-route ramp visibility. Reprise retains its cream masonry,
dark ramp edging, original lights and sky boundaries. The menu previews are
actual renderer captures: Nyx at 10% of the native recording and Reprise at 60%.
The report is `fixtures/nyx-reprise-visuals/browser-views.json`.

Peak sampled submissions were 422 draws/326,050 triangles for Nyx and 100
draws/173,972 triangles for Reprise. CPU render submission was below 0.9 ms in those
still views. These submission timings are separate from the animated benchmark
below and do not constitute a device guarantee.

## Animated rendering and delivery

The packed production assets passed five eight-second renderer routes in one
browser canvas: Nyx native, Reprise native, Nyx decoded fallback, Reprise decoded
fallback, and Nyx native again. Each route animates the camera through the full
native recording; it does not run player physics or award a time. Tests asserted
the exact requested pack URLs and that only the selected texture representation
was downloaded. No browser errors occurred.

| Map / texture path | Average FPS | p95 frame interval | Longest measured frame | Local preparation |
| --- | ---: | ---: | ---: | ---: |
| Nyx / native | 359.3 | 2.9 ms | 16.6 ms | 609 ms |
| Reprise / native | 360.0 | 2.9 ms | 3.0 ms | 238 ms |
| Nyx / decoded | 360.0 | 2.9 ms | 3.0 ms | 957 ms |
| Reprise / decoded | 360.0 | 2.9 ms | 2.9 ms | 340 ms |
| Nyx / native repeat | 360.0 | 2.9 ms | 2.9 ms | 604 ms |

These local 1280×720 balanced-quality results reflect the machine and its
apparent 360 FPS cap. Preparation uses a local development server and is not an
internet download prediction. First/repeated Nyx ended with the same renderer
counts: 535 geometries, 96 textures and 16 programs. This is a disposal regression
check, not a measurement of total browser or GPU memory. The animated route peaked
at 407 draws/337,462 triangles for Nyx and 104 draws/174,140 triangles for Reprise.

| Packed visual transfer, including manifest | Native | Decoded fallback |
| --- | ---: | ---: |
| Nyx | 18,005,464 bytes / 9 requests | 19,908,725 bytes / 8 requests |
| Reprise | 9,910,328 bytes / 7 requests | 10,859,786 bytes / 6 requests |

The retained evidence is `fixtures/nyx-reprise-visuals/performance.json` and
`packed-transfer.json`. Reproduce with `scripts/new-map-render-performance.ts`
and `RENDER_CASES='[["nyx","native"],["reprise","native"],["nyx","fallback"],["reprise","fallback"],["nyx","native"]]'`.

## Remaining rendering differences

- Original diffuse LDR lightmaps are retained. Source HDR exposure/tonemapping,
  directional bumped lightmaps, complete self-illumination and SSBump/lighting
  response are not equivalent to the browser renderer. No exposure boost was
  applied to make the authored Nyx cave brighter.
- Nyx's water and refraction passes, material scrolling, animated credits,
  rotating portal effects, particles, spotlights/laser beams and map soundscapes
  are not reproduced. Its 21 dynamic portal meshes use their original initial
  poses. Main route geometry does not animate.
- Nyx's 33 entity crack decals and Reprise's one glass decal are not projected.
  Dynamic entity visibility and general map I/O remain outside visual scope.
- Nyx's two fog controllers have identical values; the selected authored purple
  fog is unambiguous. Native PVS/areaportal culling is not reproduced; actual
  geometry and the authored sky-depth pass control the inspected occlusion.
- Native visual parity is not certified. The two explicit skin fallbacks and
  the effects above remain limitations rather than hidden corrections.
