Advertise temporal gravity fog program
This commit is contained in:
parent
5ae798c6d7
commit
636cff4878
9 changed files with 106 additions and 10 deletions
|
|
@ -226,7 +226,13 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
var shader = AetheriaRuntimeAssets.ProjectManifest(null).Assets.Single(asset =>
|
||||
asset.Ref.AssetKey == "shader.environment.gravity-fog");
|
||||
Require(shader.Ref.Metadata["unity.volume.texturePort.surfaceHeight"] == "_NebulaSurfaceHeight" &&
|
||||
shader.Ref.Metadata["unity.volume.pass.raymarch"] == "0",
|
||||
shader.Ref.Metadata["unity.volume.pass.raymarch"] == "0" &&
|
||||
shader.Ref.Metadata["unity.volume.pass.temporal"] == "1" &&
|
||||
shader.Ref.Metadata["unity.volume.pass.composite"] == "2" &&
|
||||
shader.Ref.Metadata["unity.volume.texturePort.currentSample"] == "_UndersampleCloudTex" &&
|
||||
shader.Ref.Metadata["unity.volume.texturePort.history"] == "_MainTex" &&
|
||||
shader.Ref.Metadata["unity.volume.matrixPort.previousViewProjection"] == "_PrevVP" &&
|
||||
shader.Ref.Metadata["unity.volume.floatPort.resetHistory"] == "_ResetHistory",
|
||||
"provider asset metadata must own the concrete Unity volume-program ABI projected into runtime variants");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -794,7 +794,7 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root)
|
|||
"\"org.gamecult.cultlib\": \"https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13\"",
|
||||
"\"org.gamecult.eve.plugin-fields\": \"https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.0\"",
|
||||
"\"org.gamecult.eve.surface\": \"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2\"",
|
||||
"\"org.gamecult.eve.unity-scene\": \"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.37\""
|
||||
"\"org.gamecult.eve.unity-scene\": \"https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.38\""
|
||||
};
|
||||
|
||||
var missingManifestSymbols = requiredManifestSymbols
|
||||
|
|
@ -813,7 +813,7 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root)
|
|||
"cultlib-unity-v1.0.13",
|
||||
"eve-plugin-fields-unity-v0.2.0",
|
||||
"eveunity-surface-v0.2.2",
|
||||
"eveunity-scene-v0.3.37",
|
||||
"eveunity-scene-v0.3.38",
|
||||
"\"source\": \"git\""
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
|
||||
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.0",
|
||||
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2",
|
||||
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.37"
|
||||
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.38"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@
|
|||
"hash": "140e1bd963a0033e66777a3b2c5fe6e9c97dfe32"
|
||||
},
|
||||
"org.gamecult.eve.unity-scene": {
|
||||
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.37",
|
||||
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.38",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
"com.unity.mathematics": "1.3.2",
|
||||
"com.unity.modules.particlesystem": "1.0.0"
|
||||
},
|
||||
"hash": "5ce654800760203154132d4b0fd1475294283ba6"
|
||||
"hash": "de580fe88350f422e30f1e4b64ded5c33070b118"
|
||||
},
|
||||
"com.unity.modules.assetbundle": {
|
||||
"version": "1.0.0",
|
||||
|
|
|
|||
|
|
@ -718,7 +718,10 @@ public class DaemonRuntimeDocumentTests
|
|||
Assert.IsTrue(assetManifest.Assets.Any(asset =>
|
||||
asset.Ref.AssetKey == "shader.environment.gravity-fog" &&
|
||||
asset.Ref.Kind == AetheriaRuntimeAssetKinds.Shader &&
|
||||
asset.Ref.Metadata["unity.volume.texturePort.surfaceHeight"] == "_NebulaSurfaceHeight"));
|
||||
asset.Ref.Metadata["unity.volume.texturePort.surfaceHeight"] == "_NebulaSurfaceHeight" &&
|
||||
asset.Ref.Metadata["unity.volume.pass.temporal"] == "1" &&
|
||||
asset.Ref.Metadata["unity.volume.texturePort.currentSample"] == "_UndersampleCloudTex" &&
|
||||
asset.Ref.Metadata["unity.volume.texturePort.history"] == "_MainTex"));
|
||||
Assert.IsTrue(assetManifest.Assets.Any(asset =>
|
||||
asset.Ref.AssetKey == "texture.environment.volume-dither" &&
|
||||
asset.Ref.Kind == AetheriaRuntimeAssetKinds.Texture));
|
||||
|
|
|
|||
|
|
@ -267,9 +267,59 @@ Shader "Aetheria/CloudShader"
|
|||
float4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float3 vspos = float3(i.vsray, 1.0);
|
||||
// float4 worldPos = mul(unity_CameraToWorld, float4(vspos, 1.0f));
|
||||
// worldPos /= worldPos.w;
|
||||
float4 raymarchResult = tex2D(_UndersampleCloudTex, i.uv);
|
||||
if (_ResetHistory >= 0.5f)
|
||||
return raymarchResult;
|
||||
|
||||
float distance;
|
||||
float density;
|
||||
float density2 = 0.0f;
|
||||
unpack(raymarchResult.a, distance, density);
|
||||
distance *= _ProjectionParams.z;
|
||||
|
||||
half outOfBound;
|
||||
float3 previousWorldPosition = mul(
|
||||
unity_CameraToWorld,
|
||||
float4(normalize(vspos) * distance, 1.0f)).xyz;
|
||||
float2 prevUV = PrevUV(float4(previousWorldPosition, 1.0f), outOfBound);
|
||||
float4 prevSample = tex2D(_MainTex, prevUV);
|
||||
float2 xoffset = float2(_UndersampleCloudTex_TexelSize.x, 0.0f);
|
||||
float2 yoffset = float2(0.0f, _UndersampleCloudTex_TexelSize.y);
|
||||
float4 m1 = 0.0f;
|
||||
float4 m2 = 0.0f;
|
||||
|
||||
[unroll]
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
[unroll]
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
float4 value;
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
value = float4(raymarchResult.rgb, distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = tex2Dlod(
|
||||
_UndersampleCloudTex,
|
||||
float4(i.uv + xoffset * x + yoffset * y, 0.0f, 0.0f));
|
||||
float neighborDistance;
|
||||
unpack(value.a, neighborDistance, density2);
|
||||
value = float4(value.rgb, neighborDistance);
|
||||
}
|
||||
m1 += value;
|
||||
m2 += value * value;
|
||||
}
|
||||
}
|
||||
|
||||
float4 mean = m1 / 9.0f;
|
||||
float4 sigma = sqrt(abs(m2 / 9.0f - mean * mean));
|
||||
prevSample = ClipAABB(mean - 0.5f * sigma, mean + 0.5f * sigma, prevSample);
|
||||
raymarchResult = lerp(
|
||||
float4(prevSample.rgb, density),
|
||||
float4(raymarchResult.rgb, density2),
|
||||
max(0.05f, outOfBound));
|
||||
return raymarchResult;
|
||||
}
|
||||
ENDCG
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
["unityAssetPath"] = "Assets/Shaders/Raymarching/CloudShader.shader",
|
||||
["presentationRole"] = "environment.gravity-fog.volume",
|
||||
["unity.volume.pass.raymarch"] = "0",
|
||||
["unity.volume.pass.temporal"] = "1",
|
||||
["unity.volume.pass.composite"] = "2",
|
||||
["unity.volume.quality.high.keyword"] = "HIGH_QUALITY",
|
||||
["unity.volume.quality.normal.keyword"] = "MEDIUM_QUALITY",
|
||||
|
|
@ -234,11 +235,15 @@ namespace GameCult.Aetheria.State.Verse
|
|||
["unity.volume.texturePort.patch"] = "_NebulaPatch",
|
||||
["unity.volume.texturePort.tint"] = "_NebulaTint",
|
||||
["unity.volume.texturePort.dither"] = "_DitheringTex",
|
||||
["unity.volume.texturePort.currentSample"] = "_UndersampleCloudTex",
|
||||
["unity.volume.texturePort.history"] = "_MainTex",
|
||||
["unity.volume.texturePort.cloud"] = "_CloudTex",
|
||||
["unity.volume.vectorPort.viewportTransform"] = "_GridTransform",
|
||||
["unity.volume.matrixPort.cameraInverseViewProjection"] = "_CamInvProj",
|
||||
["unity.volume.matrixPort.previousViewProjection"] = "_PrevVP",
|
||||
["unity.volume.vectorPort.cameraProjectionExtents"] = "_ProjectionExtents",
|
||||
["unity.volume.floatPort.raymarchOffset"] = "_RaymarchOffset",
|
||||
["unity.volume.floatPort.resetHistory"] = "_ResetHistory",
|
||||
["unity.volume.vectorPort.ditherCoordinates"] = "_DitheringCoords",
|
||||
["unity.volume.floatPort.fillDensity"] = "_NebulaFillDensity",
|
||||
["unity.volume.floatPort.fillDistance"] = "_NebulaFillDistance",
|
||||
|
|
|
|||
|
|
@ -865,6 +865,38 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted.
|
|||
height, and negative body splats. Released cold/warm witnesses exercise the
|
||||
persisted daemon path.
|
||||
|
||||
### Gravity Fog Presentation Contract
|
||||
|
||||
- Owner: Aetheria owns the gravity/fog splat values, authored volume tuning, and
|
||||
provider shader asset. Eve Fields owns the portable splat document and
|
||||
`field.volume3d` logical ports. EveUnity owns only the native render lifecycle.
|
||||
- Inputs: the canonical viewport splat document, logical surface-height,
|
||||
patch-height, patch, tint, scalar/vector parameters, provider asset reference,
|
||||
and the selected runtime asset variant's native program metadata.
|
||||
- Outputs: the generic runtime rasterizes logical field layers, executes the
|
||||
advertised raymarch, optional temporal-history, and composite passes, and
|
||||
presents pixels. No pass can emit gameplay state or commands.
|
||||
- Derived state: Unity materials, shader-property names, pass indices, keywords,
|
||||
raymarch targets, ping-pong history textures, previous camera matrices, and
|
||||
composite counters are runtime projections. They are neither daemon truth nor
|
||||
portable Eve state.
|
||||
- Forbidden writers: the old `VolumeSampling`/`VolumeCloudRenderer` presentation
|
||||
path, shader code, Unity cameras, and generic lowerers cannot calculate gravity,
|
||||
move bodies, or publish world truth. EveUnity may not import an Aetheria assembly
|
||||
or branch on Aetheria asset identities.
|
||||
- Shared paths: first frame, camera motion, reconnect, viewport resize, and warm
|
||||
asset reuse all enter the same generic volume lifecycle. History resets on a
|
||||
new node, program, or render size. A provider that advertises a temporal pass
|
||||
without all required history ports fails closed.
|
||||
- Cut line: the portable surface contains logical field and parameter names only.
|
||||
`_Nebula*`, `_PrevVP`, `_ResetHistory`, shader keywords, and pass indices live
|
||||
exclusively in the provider's Unity asset-variant metadata.
|
||||
- Verification layer: EveUnity package tests prove two-pass compatibility,
|
||||
complete temporal-program acceptance, partial-program rejection, and absence
|
||||
of Aetheria assembly references. Aetheria daemon smoke proves the exact fossil
|
||||
shader ABI is advertised outside the portable surface. A live capture is still
|
||||
required for visual parity.
|
||||
|
||||
### Daemon Asset Content Delivery
|
||||
|
||||
- Owner: the Aetheria daemon owns bundle content and serves bytes only through
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ validation proves contract shape, not wiring, exclusivity, lowering, or parity.
|
|||
| Pilot camera | ARPG follow/dock cameras | Eve view semantics + runtime | camera rig and semantic view id | EveUnity camera rig | authored ARPG follow distance, field of view, screen framing, and damping are provider-owned and generically lowered; dock/view transition parity remains absent | dock transition timeline and reconnect |
|
||||
| Render channels | Unity layers/culling masks | provider surface policy + runtime asset variant | semantic channel exclusions | EveUnity native layer mapping | wired, exclusive, and lowered: the pilot surface excludes the semantic `map` channel; the Unity asset variant maps `map` to its authored native layer; EveUnity subtracts that layer from the configured camera mask; portable state contains no Unity layer or mask; package tests and the clean-client dependency verifier pass | live pilot capture proving no map glyphs while the map camera retains them |
|
||||
| Minimap/tactical map | `ZoneRenderer`, map cameras | daemon world facts | explicit map projections | Unity and Electron | facts fragmented; generic lowerers absent | same state in both runtimes |
|
||||
| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | owner-exists; basic lowering; composition parity absent | visual parity captures |
|
||||
| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | daemon publishes four canonical gravity/fog splat layers through `field.volume3d`; the provider asset variant owns the fossil shader, native ports, quality/features, and raymarch/temporal/composite pass graph; released EveUnity `0.3.38` lowers the optional temporal-history lifecycle generically and fails closed on partial native programs; the warm released witness executes the provider bundle, four layers, and repeated composites without importing Aetheria code; the current pilot capture remains nearly black/geometric rather than the authored blue fog sea, so visual composition parity is explicitly absent | diagnose field values, colour/exposure/composition and camera-depth behavior against the fossil, then capture temporal stability and visual parity |
|
||||
| HUD/schematic | ARPG HUD and `SchematicDisplay` | Eve composition from daemon facts | semantic status/components | EveUnity UI | provider-authored transparent cockpit is wired, projected, and lowered through generic UI Toolkit panes, metrics, and progress components for hull, shield, capacitor, temperature, cargo, weapon cooldown/groups, selected target, target lock, target shield, and target hull; the original armor/equipment schematic and transient warning choreography remain reference-only | schematic topology, warning timelines, dynamic action state, and composited live capture |
|
||||
| Hit/lock/warnings | `ActionGameManager` feedback | daemon event facts | transient feedback stream | VFX/UI/audio | bounded deduplicated game-event ledger and Eve `feedback.stream` wired for pickup outcomes, projectile launch/impact, entity damage, alive-to-dead destruction, authoritative weapon reload chronology, and episode-deduplicated `weapon.fire.refused` facts for insufficient energy or missing ammunition; refusal identity, authored weapon, target, reason, and remaining magazine state are runtime-independent cockpit inputs | add lock transitions, thermal and docking event families, negative transaction fixtures, and runtime effect consumption |
|
||||
| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | provider manifests name deterministic bundle-internal paths; the authoring build derives presentation-only prefabs, strips missing and non-Eve `MonoBehaviour` components, verifies both saved prefabs and the loaded bundle, and publishes the immutable bundle through CultMesh; released-client warm-cache loading, content verification, and rendered provider identity are proven, while cold transfer still times out because the 46.1 MB body travels through batched snapshot records | mapped/network body transport followed by empty-cache download, atomic promotion, and cache reuse proof |
|
||||
|
|
|
|||
Loading…
Reference in a new issue