SEAFORGE v1.2
The sea goes under. Two underwater stages, a sea that mirrors your sky, and a net that gives when you hit it.
In one screen
| What changed | What it gives you |
|---|
New : EnvAqua | A sunlit underwater stage on one Empty. Sand that takes her weight and keeps the mark, caustics that follow her, light curtains, a reef, and fish that know she is there : a school that keeps its distance, parts around her, and can dance along with her on cue. |
New : EnvDeepSea | The deep version. Water that goes from blue-black to red-black on one slider, marine snow and fines drifting on a current, a mottled surface far overhead, a caustic cookie that lights only the performers, ripples on the seabed that lie across the current. |
EnvBeach : the sea mirrors your sky | Physical optics is the default now. The sea reflects the skybox that is actually in your scene, the sun on the water is the sun in that sky, and the surface carries a wind sea : short chop under the swell, with a wind speed and a direction. +0.17 ms at 8K. |
New : PropNet | A volleyball net that stretches around her when she leans into it, snaps back, and settles still. Posts, tape and cords from one Empty, no asset. |
Three factory nights | Every price on this page comes from an unattended 8K bench with a frozen identity : four passes per row, a 4.5 hour rotation soak, and a reader that judged the result before anyone looked at a number. The night that found a defect is on this page too. |
Reviewed before release | A full behaviour and ownership audit of all four products, a third-party re-review, two re-verification rounds, four functional regression cards and a load-from-the-package check, all before this went out. |
Your saved beach scenes load unchanged. The one visible change in an old scene is the sea's reflection : it now mirrors the sky you gave it instead of a painted sky colour. If you want the v1.1 look back,
Sea optics β Classic is one chooser on the SEA page, and it is a storable like everything else.
Where it came from
v1.1 was a shore seen from the beach. The page said so, and said where the rest was going : the same field that knows where the sand is and how far the water reaches also knows how deep the water is at every point, and that is the floor of going under.
Going under turned out to be two different places, not one. Just below a sunlit surface the water is bright, the sand is close, the caustics move, and there is life in it. Deep down there is no surface worth drawing, the colour of the water is the whole mood, and what moves is snow, fines and the occasional jellyfish. Making one plugin do both would have meant a panel where half the controls are wrong for whichever one you are in. So there are two,
EnvAqua and
EnvDeepSea, and each one is built the way the beach was : drop it on an Empty, and it is already happening.
The sea itself got the upgrade it was owed on the way. The v1 sea reflected a sky colour we painted. Now it reflects
yours.
EnvAqua : the sunlit shallows, and the fish that live there
What it does
Add an Empty, load
EnvAqua.cslist. The Empty is the bottom of the sand; its +Z is the front. Around it : a sand bed that takes impressions and lets them settle, a coral reef with its opening toward you, seaweed and seagrass swaying in the current, suspended motes, light curtains falling from the surface, and a surface overhead with the same wind sea the beach has, seen from below.
The sand is the beach's sand. Press into it and it keeps the shape; the edges round off and slump on their own; lift a limb out and it sheds a soft cloud of haze and heavier grains that settle back. Recovery is a half-life you set, up to a day, and it ships off so a mark stays until you clear it.
Caustics on her. A caustic light is aimed at the performance area : natural caustic patterns, or crossed bands, in a colour you choose, moving with the water. The seabed gets its own.
A scene light can shadow the sand : pick one native light with shadows on, and the sand and every impression in it receive that light's real shadows. Nothing else in the stage is touched.
The fish are not a texture that scrolls past
There are two kinds of life here, and the difference is the point of this release.
The distant schools are the backdrop : small shoals in the middle distance that turn and glint. They do what accepted schools do, and they are cheap.
The nearby school is something else. It is a bounded, independent group that lives in the water around the stage's centre, where she performs, and it knows where she is :
It keeps its distance. Every fish has an avoidance radius. Walk toward them and the school parts and closes behind you; stand still and it drifts back in. Nothing is scripted around a position you chose.
It can dance with her. Behaviour β Dance along makes the school pick up her movement and swim with it, which is one trigger in a choreography and one trigger back to Natural swimming when the number ends.
Three species, one chooser. Silver reef fish, clownfish, or jellyfish. Switching species sets the right body size, and the jellyfish come with their own locomotion : a short power stroke, a longer recovery, a coast, so they pulse and drift instead of swimming like fish with a bell on.
Mouth bubbles on cue. A breath from her lips is one action, AquaExhaleBubbles, placed from the lips with a positioning aid you can switch on while you set it and off when you are done.
None of it asks her for anything. The school reads her body; it never pushes on it. The sand applies no force to her either : impressions come from contact samples, so her physics are exactly what they were before you added the plugin.
Put it on an Empty, and keep the front open
The reef opening faces the Empty's +Z. Cameras that pull back should pull back through that opening, which is what it is for. Core is the clear performance area and ships at 24 m; larger is a stress setting because the sand bed is pre-built as patches on a grid that gets finer with the area.
EnvDeepSea : the deep, where the colour is the mood
What it does
Add an Empty, load
EnvDeepSea.cslist. Dark water with a visibility you set, marine snow and fines drifting on a current with a heading, a slow upwelling, and a mottled light far overhead : the beach's wind sea seen from a long way below, with a sun glow and glitter in the direction the caustic comes from.
Colour transition is one slider between two endpoints you can both edit : blue-black at one end, red-black at the other, and the jellyfish, the bubbles and the caustic can follow the palette or keep their own colour. It is artistic colour, not lighting; keep her key light.
The caustic lights only the performers. A cookie light on a stage would normally paint every rock and prop in the scene with the same ripple.
Cookie on performers only keeps it off everything that is not part of a Person atom : scene geometry, CUA props, a stage's own set. Rocks stay rocks; she ripples. A name list lets you keep the caustic on something by name (
shark, rays for a stage's animals), and a host that owns render layers for its set can name those layers instead of having anything moved.
The seabed has a current. Ripples lie across the current heading, 12 cm ripples on 95 cm megaripples, with dark detritus in the troughs near the camera, and the sand's direct light comes from the caustic's direction. The classic sediment look is one chooser away.
Jellyfish and mouth bubbles are the same creatures as the shallows', in the deep palette, and they run with the sand off.
Two stages, one Empty each, one at a time
Aqua and DeepSea are separate scenes. They share their sand, their jellyfish and their wind sea in code, but each builds its own stage, so they go on their own Empty and you switch between them with their Master Switches rather than running both at once.
EnvBeach : the sea mirrors your sky
What changed
The v1 sea reflected a sky colour we painted into the shader : three colours from the shallows to the horizon, a sun direction from two sliders. It looked like a sea. It did not look like
your sea, because it had never seen your sky.
Physical optics finds the skybox that is actually in your scene, copies its panorama once, and reflects it : the clouds you placed are the clouds on the water, the sun on the water is the sun in that image, measured in the image rather than guessed. Under it runs a
wind sea : the short chop that real water has under its swell, with a wind speed and a direction, so the reflection breaks the way a reflection on moving water breaks.
Sea optics (SEA page) : Physical is the default now; Classic is the v1.1 look, unchanged.
Wind speed, wind direction, chop amount : they act under Physical only.
Built-in sun follows the sky's sun (LIGHT page, off by default) : points the beach's own light where the sun in your sky actually is. The sea reads it anyway; this is for the sand's glitter.
Rebuild sky reflection : an action, for when you swap skyboxes at run time and want the copy refreshed now rather than on the next detection.
What it needs, and what happens without it
It needs a sky in the scene : a skybox CUA, or any large background sphere with a lat-long panorama on it (a stage kernel's own sky counts; the plugin recognises one by its geometry, not its name). It keeps looking for one, so a sky that loads late, or one you switch on later, is found within a few seconds.
With no sky at all the sea falls back to the classic colour, and the Report says so in words.
PropNet : a net that gives
Add an Empty where the net should stand, load
PropNet.cslist. Posts, tape and net appear at regulation beach dimensions. Walk a Person into it : the cords stretch around her, hold, and snap back when she steps away; a hard shove makes the cord let go of her rather than dragging the whole net across the court. It settles still on its own and sleeps when nothing is touching it. No asset, no model : a plugin and a shader.
PropNet was not on the factory bench. It is here because it is finished and it ships in the same package; its price is not on this page because it was not measured there, and we do not print numbers we did not take. Its own Report prints what it costs on your machine.
What it costs
Bench, 7680x4320 with 4x MSAA, one RTX 5090, panels closed, VSync off.
Four passes of ten seconds per row, every setting written by the harness. The floor is a scene with the products loaded and switched off,
loaded with 128 ballast quads so the frame is GPU-bound : without that, a cost sits under the CPU floor and reads smaller than it is. More on that under the beach row.
The underwater stages
| Framing | EnvAqua, shipped | EnvDeepSea, shipped |
|---|
| Looking up at the surface | +0.92 ms | +0.65 ms |
| Her, at chest height (the shot you will take) | +1.31 ms | +1.90 ms |
| Down at the sand | +1.08 ms | +1.98 ms |
| Low, near the bed | +1.33 ms | +1.50 ms |
| Wide, the whole stage | +1.32 ms | +1.66 ms |
Both stages, everything on, at the shot you will actually take : under 2 ms at 8K.
Inside those numbers, the parts that have their own switch :
| What | Reading | What it means |
|---|
| DeepSea haze (the depth-aware water column) | +0.38 ms, of which 0.04 is a depth pre-pass | If your scene already renders a depth texture for something else, the haze costs 0.34. |
| DeepSea overhead wind sea vs the classic mottle | +0.07 looking up, +0.03 at her, +0.02 at the sand | It is a surface far away; it costs where it fills the frame. |
| DeepSea seabed ripples vs classic sediment | +0.33 at the sand, +0.43 at her, +0.44 wide | The ripple field costs by how much seabed is on screen, not by how close you are. |
| Aqua surface wind sea vs classic ripples | +0.07 to +0.08 at every framing | Flat. The FFT is a fixed cost and the surface is small from below. |
| Wind speed 3 / 6 / 12 m/s, either stage | within 0.06 ms of each other | The spectrum is rebuilt once per change; the per-frame work does not depend on the wind. |
The beach
| What | Reading |
|---|
| EnvBeach, factory settings, Physical optics (sand + sea + surf + prints), mid framing | +6.46 ms over the ballasted floor |
| of which Physical optics over the Classic sea : mid / far / grazing | +0.17 / +0.17 / +0.11 ms |
| the sky mirror itself / the wind sea, at mid | +0.16 / +0.02 ms |
| SkinBeach, everything on (shell, ledger, shake-off, wipe-off, thrown sand), moving | under 0.2 ms : the table's own drift over the run was 0.2, so that is the bound, not the price |
β Why the beach reads 6.5 ms here and 4.2 ms on the v1.1 page
The v1.1 bench had nothing else on the GPU, so its floor was the CPU : 3.41 ms. A GPU cost measured against a CPU floor shows only the part that sticks out above it, and
that is a lower bound, not a price. Before trusting the new number we loaded the exact v1.1 package and the current beach into the same scene, same camera, same ballast, four loads alternating :
v1.1 read +6.24 and the current Classic sea +6.21, within 0.03 ms of each other. Nothing regressed; the earlier bench could not see the whole bill. The v1.1 page's number is corrected on the main page, and the method that produced it is retired.
The price does not depend on how loaded your GPU already is
The same three products priced against 128 and then 192 ballast quads : DeepSea 1.88 / 1.90, Aqua 1.29 / 1.30, the beach 6.46 / 6.42. Within 0.05 ms. The ballast itself is linear (+4.6, +4.3 ms per step), which is the check that the bench can read what it prints.
So the number you get on your machine is the number above plus whatever your scene already costs, not some multiple of it.
Five and a quarter hours, unattended, three stages in rotation
After the pricing tables the bench walks her through each stage for 90 minutes, everything on, then switches to the next, round and round until the morning. 317 one-minute buckets; the three segments judged are the full ones.
Frame time did not drift. First fifth against last fifth of each segment : DeepSea 12.42 β 12.37 ms, Aqua 11.40 β 11.40, Beach + SkinBeach within the same 0.3 ms limit. p95 tracked the mean in all three, so no stutter grew in.
No leak. Meshes, materials, textures, render targets and GameObjects were counted every few minutes : identical at the end of each segment to the start of its last two thirds. The managed heap saw-tooths the way any Unity app does; its floor after a collection is the number a leak would move, and it did not.
Everything that should have been running was running, every minute. Each product publishes live counters : DeepSea's update, chop, step and jellyfish counts climbed in every bucket; Aqua's in its segment; the beach's optics read 2 (Physical, mirroring a sky) and its wind sea ran at 60 Hz in every bucket of its segment; nothing latched a failure all night.
One frame over 100 ms in each of the first two segments, at 38 and 147 minutes, none in the third : VAM's garbage collector, the same hitch the main page describes, about 330 ms. Everything else stayed under 35 ms including the bench's own census.
Three nights, and what the second one found
The factory run was done three times, not because the first two failed to produce numbers but because the identity the numbers belong to has to be the identity that ships.
- Night one (10-09) ran at three passes. Its verdict was incomplete : the reader's own switch-over tolerance was too tight for a product that counts 1500 steps a row, two of our 09-24 predictions turned out to be wrong, and four criteria sat within 0.02 ms of their limits, which three passes cannot resolve. Nothing in the products. The instrument was corrected and the night was rerun at four passes.
- Night two (10-10) found the defect. Physical optics had become the default that afternoon, after the v1.1-against-current A/B above. The very first table of the night switches the sky off for its underwater rows and back on for the beach rows, and the beach rows then read optics 1 : Physical, no sky. The beach had looked for the sky, missed it five times over 15 seconds while the bench held it off, and then never looked again. Every later table read 2, because the optics table happens to switch Classic β Physical, which re-triggers the search. A user whose skybox loads a few seconds after the beach would have seen the classic colour until they touched a control. Fixed the same morning : while Physical holds no sky, the beach looks again every five seconds, and switching it on looks at once; nothing runs while a sky is held. Reproduced and verified on the machine before the third night.
- Night three (10-11) is the one on this page. Complete, every row at four valid passes, the soak a full rotation, the beach rows reading 2 from the first table on. Two criteria still came in over their fixed limits, both by less than the rows' own pass-to-pass spread : a wind-speed pair at +0.062 against 0.05, and SkinBeach's first and last rows 0.2 ms apart over a 7-minute table. They are printed as what they are : the resolution of the bench, which is why SkinBeach's price is given as a bound.
The 4.18 β 6.46 correction and the sky defect are both the product of the same decision : measure the shipped configuration, on the bench it will actually be judged by, and let the reader judge it before anyone chooses what to print.
Changelog
| Where | What |
|---|
| New | EnvAqua, EnvDeepSea, PropNet, each on its own Empty, each with a Master Switch, a Report and a full trigger API. |
| EnvBeach | Sea optics : Physical (default) mirrors the scene's sky and runs a wind sea; Classic is the v1.1 look. New : seaOptics, seaWindSpeed, seaWindDirDeg, seaChopAmount, seaSkyMirrorView, lightSunFollowsSky, actions seaRebuildSky, seaCaptureAB. |
| EnvBeach | A sky that appears after the beach has stopped looking (a late-loading skybox, one switched on later) is found again within five seconds; switching the beach on with no sky held looks at once. |
| EnvBeach | Reject lights at the source gives every light back exactly the bit it had : switching the feature off, Master off, disabling or removing the plugin all restore the original culling masks, and a light added while it is off is never touched. Its render layer is a lease and is re-picked each time, so it cannot collide with a sibling plugin that leases layers too. |
| EnvBeach | Unticking the plugin in the list now puts the beach to sleep instead of freezing it on screen; re-ticking wakes it. Settling no longer runs forever on a flat, unmarked field. A redundant full-field wetness write after the sea is switched off is gone. |
| SkinBeach | A skin submesh hidden by a clothing item's Disable anatomy and shown again gets its sand shell at once, with the colour and coverage set while it was hidden. Master off β on no longer shakes sand loose for one frame. Four retired parameters and one action are no longer registered (listed in the API table); the sticking contract moved to v3 and reads the ground the beach actually draws, including the print rim. |
| All four | Every per-frame shader write uses a cached property id (762 call sites across 13 files); the panel builds no strings while it is closed; the Report prints the shader generation it is talking to and refuses to call an old bundle live. |
| Package | One .var, five plugins, three bundles, the five readmes and the Beach / Skin API table. The development folder (QA runs, audits, plans) stays out of the package. |
Compatibility. Every v1.1 storable keeps its id and meaning. The
seaOptics chooser's option text changed when Physical became the default; a scene that saved the old text loads correctly, and a trigger that still writes the old text still works.
Known limits, stated rather than claimed fixed
- The sea needs a sky to mirror. No skybox, or a sky drawn by something that is not a sphere with a panorama on it, and the sea shows the classic colour. The Report names what it found and what it is mirroring.
- Aqua and DeepSea are stages, not a dive. You do not swim from the beach down into them; each is its own scene on its own Empty. Run one at a time.
- The nearby school is bounded. It lives in a radius around the stage centre, 1.35 m by default; it will not follow her out of the water or across a large set.
- Core above 24 m is a stress setting on both underwater stages. The sand bed is pre-built as patches on a grid that gets finer with the area (1,156 patches at 24 m, 5,476 at 32 m); rebuild time and memory grow with it and were not priced.
- Scene shadows on Aqua's sand borrow a render layer while a source light is selected, the same way the beach's light rejection does. Another plugin that also edits culling masks or leases layers will fight it; pick one.
- DeepSea's performer-only caustic moves scene objects to render layer 26 while it is on, and moves them back when it is off. A plugin that reads object layers for its own purposes will see 26 while DeepSea runs.
- PropNet collides with Person bodies only; a ball is wired by trigger, not simulated by the net. Its performance was not benched this round.
- Transparent against transparent still has no correct order. Light curtains, motes, haze, bubbles and jellyfish membranes each carry a render queue slider, with -1 meaning the product's own default. Author's call, per scene.
What we did not change
- The sand, the prints, the surf and the body work. Not a line of their look. The beach that v1.1 users have is the beach they get, with a better reflection on the water.
- Aqua's own caustic light has no scope. Unlike DeepSea's, it lights the stage's own scenery as well as her, because the shallows were accepted that way. Scoping it would change the stage's look, so it stays; both cookies have a row in the pricing tables.
- Two shader simplifications an audit proposed were left alone : one turned out to be already done by the compiler (22 texture taps where the source reads 38), and the other sits below what the bench can resolve. Filed, not forgotten.
Reviewed before release
- A full behaviour and ownership audit of all four products (91 items), then a third-party re-review (13 items, three of them code-level), then two re-verification rounds of the fixes. Everything is fixed or written down as a limit above. The part worth passing on is what kind of things they were : a bundle request arriving while a plugin was switched off and being treated as a duplicate; a render-layer bit OR'ed back into every scene light one frame after it had been restored; a hidden skin submesh missing its binding forever. All three are regression cards now.
- Four functional cards, run on the machine, one button each : the held bundle request builds once when switched on (6 of 6 checks); DeepSea's name list and a renamed atom (6 of 6); the beach's light rejection across off, Master off, plugin disabled and plugin removed (13 of 13); SkinBeach's shell under Disable anatomy (4 of 4). The cards failed four times before they passed, every time on the instrument rather than the product, and those runs are kept.
- Loaded from the package with the loose folder emptied : all five plugins resolve their bundles from the .var, the beach mirrors the sky from the first frame, the net builds. 18 of 18 checks.
Every test that was run, and what it returned
| Test | What it asked | Result |
|---|
| Ballast linearity | Can the bench read the differences it is about to print | +4.61 / +4.30 ms per 64 quads, each step resolved |
| Price vs load | Does a product's cost depend on the GPU load around it | DeepSea 1.88 / 1.90, Aqua 1.29 / 1.30, Beach 6.46 / 6.42 at 128 / 192 quads |
| Negative controls | Does rewriting a value the pin already holds move the frame | Wind, jellyfish count : 0.000 and 0.058 ms, within the pair's own spread |
| Positive control | Is a real switch visible to the bench | DeepSea's sand off : 1.2 ms cheaper |
| Drift anchors | Does the first row still read the same at the end of each table | within 0.08 ms on every table but SkinBeach, where the 0.2 drift became the price's bound |
| DeepSea by framing | What does the stage cost where the camera looks | 0.65 to 1.98 ms across five framings |
| Aqua by framing | Same | 0.92 to 1.33 ms |
| Overhead wind sea | Does the surface cost more where it fills the frame | UP 0.07 > FEET 0.02, as predicted |
| Seabed ripples | Do the ripples cost more at the feet than wide | No : 0.33 at the feet, 0.44 wide. The 09-24 prediction was wrong and is recorded, not enforced |
| Wind speed | Does 3 / 6 / 12 m/s change the frame | within 0.06 ms on both stages |
| Haze | What does the depth-aware water column cost, and how much is the depth pre-pass | 0.38 total, 0.04 of it the pre-pass |
| Physical optics by framing | What does the sky mirror add | +0.17 / +0.17 / +0.11 at mid / far / grazing; NEAR sits on two GPU price levels and is not quoted |
| Sky mirror split | How much of Physical is the mirror and how much the wind sea | 0.16 mirror, 0.02 wind sea; the mirror is a texture lookup and reads at the floor |
| v1.1 against current | Did the beach regress since the release | +6.24 vs +6.21 ms, same scene, five loads alternating |
| Beach give-back ladder | Does each give-back save something, and never cost | never dearer; octaves 8 β 4 saves 0.64, micro relief 0.45, grain 0.15, 1.5 ms in all at mid framing |
| SkinBeach smoke | Does the body work cost anything the bench can see | every row within 0.05 of the skin-off row; bound 0.2 |
| Churn | Does walking her through each stage for minutes grow anything | meshes, materials, textures, RTs, objects flat across passes |
| Soak : drift / stutter / leak / liveness | Three segments of 90 minutes | all within limits, every counter climbing, no failure latched |
| Sky found at scene start | Does the beach mirror the sky in the first table of the night | Defect found on night two, fixed, on night three |
| Card R01 | A bundle request held while OFF builds once when switched ON | 6 of 6 |
| Card DEEP | Name list keeps a layer lit; a renamed atom re-counts | 6 of 6 (and one product gap closed on the day : a renamed atom's new name now matches) |
| Card R02 | Light rejection restores every light's own bit by four routes | 13 of 13 + plugin removed by hand |
| Card R03 | The shell under Disable anatomy | 4 of 4 |
| Package closure | Is the .var exactly the shipped set, byte for byte | 98 required, 98 present, 0 problems |
| Load from the package | Do all five run with no loose files | 18 of 18 |
Twenty-five tests, one defect, and it is on this page. Two predictions written before the numbers existed turned out wrong; they are recorded as wrong rather than quietly deleted.
How it was measured, and where it failed
- Four passes of ten seconds per row, with a five second settle, every setting written by the harness. A pass with a frame over 50 ms, a garbage collection or a missed write is thrown away; a row needs three valid passes to count.
- Every row carries its own proof that the thing being priced was running : the products publish live counters (updates, chop frames, steps, jellyfish, the beach's optics state, the ledger's runs), and the reader voids a pass whose counters contradict what the row declared. That is how night two's beach rows were caught : the frame times looked fine; the counter said no sky.
- The identity was frozen before each night : every product and instrument file by hash, the scenes by hash, the plan (passes, minimum valid, the soak's segments and bucket length). The reader refuses files that predate the freeze and refuses to judge a run whose instruments changed since. Night one's reader was corrected after night one, so night one's numbers are not on this page.
- The panel was closed, the browser too. One A/B load taken while a browser was open on the same GPU read 0.17 ms higher with four times the spread. It is in the archive with that note, and it was repeated.
- The NEAR framing of the beach sits on two GPU price levels about 1.8 ms apart, in both arms, in all three nights. The reader now says so instead of voiding the passes, and no NEAR price is quoted.
- Nothing here was estimated. Where a number could not be measured honestly it is not on this page; where the bench ran out of resolution we printed a bound and said why.
v1.1 was a shore, seen from the beach.
This one goes under, twice, and the sea finally reflects the sky you gave it.