Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Rendering;
|
|
|
|
|
|
|
|
|
|
namespace ShieldField
|
|
|
|
|
{
|
|
|
|
|
public enum FracturePattern { Radial = 0, Star = 1, Lance = 2, Spiral = 3, Crystal = 4, Fizzle = 5 }
|
|
|
|
|
|
|
|
|
|
public class ShieldPanel : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
// ---------------- authoring ----------------
|
|
|
|
|
[Header("Tiling")]
|
|
|
|
|
public TilingKind tiling = TilingKind.PenroseP3;
|
|
|
|
|
public float panelRadius = 5f;
|
|
|
|
|
public float cellSize = 0.35f;
|
|
|
|
|
public bool mergeRhombs = true; // Penrose triangles -> P3 rhombs
|
|
|
|
|
public bool takeDual = false; // render the dual tiling instead
|
|
|
|
|
public int seed = 1337;
|
|
|
|
|
|
|
|
|
|
[Header("Assets")]
|
|
|
|
|
public ComputeShader sim;
|
|
|
|
|
public Shader panelShader;
|
|
|
|
|
|
|
|
|
|
[Header("Materialisation")]
|
|
|
|
|
public float growDuration = 0.35f;
|
|
|
|
|
public float wavefrontSpeed = 8f;
|
|
|
|
|
public float delayJitter = 0.06f;
|
|
|
|
|
|
|
|
|
|
[Header("Wave")]
|
|
|
|
|
[Tooltip("c^2. Raise for a faster shock; watch the CFL warning in the console.")]
|
|
|
|
|
public float waveSpeed2 = 26f;
|
|
|
|
|
public float damping = 1.6f;
|
|
|
|
|
public float stressClamp = 4f;
|
|
|
|
|
[Range(1, 16)] public int substeps = 6;
|
|
|
|
|
public float fixedSubstepDt = 0.0025f;
|
|
|
|
|
|
|
|
|
|
[Header("Through-thickness echo")]
|
|
|
|
|
[Tooltip("Substeps for one round trip through the plate. Small = fast back-face spall.")]
|
|
|
|
|
[Range(1, 15)] public int echoDelaySteps = 5;
|
|
|
|
|
[Tooltip("Negative: a free back face returns the compressive pulse as tension.")]
|
|
|
|
|
public float echoReflect = -0.65f;
|
|
|
|
|
|
|
|
|
|
[Header("Material (tempered)")]
|
|
|
|
|
public float tensileStrength = 0.9f;
|
|
|
|
|
[Tooltip("Surface compression at full charge. This is the shield's hit budget.")]
|
|
|
|
|
public float temperInit = 0.55f;
|
|
|
|
|
public float temperErosion = 2.2f;
|
|
|
|
|
[Tooltip("How much stored core energy a break dumps back into the field.")]
|
|
|
|
|
public float storedEnergyGain = 0.8f;
|
|
|
|
|
public float damageGain = 6f;
|
|
|
|
|
[Range(0.05f, 1f)] public float breakAt = 0.75f;
|
|
|
|
|
[Range(0f, 0.9f)] public float crackStart = 0.18f;
|
|
|
|
|
[Tooltip("Breaks permitted per frame. Without this the cascade finishes in one frame and you see nothing.")]
|
|
|
|
|
[Range(0.001f, 1f)] public float breakBudgetFraction = 0.02f;
|
|
|
|
|
|
|
|
|
|
[Header("Shards")]
|
|
|
|
|
public float radialKick = 1.6f;
|
|
|
|
|
public float lateralKick = 2.2f;
|
|
|
|
|
public float normalKick = 1.1f;
|
|
|
|
|
public float spinKick = 7f;
|
|
|
|
|
public float shardLife = 2.5f;
|
|
|
|
|
public float shardDrag = 0.7f;
|
|
|
|
|
[Range(2, 8)] public int maxShards = 6;
|
|
|
|
|
|
|
|
|
|
[Header("Render")]
|
|
|
|
|
public float conduitGain = 2.5f;
|
|
|
|
|
|
|
|
|
|
// ---------------- runtime ----------------
|
|
|
|
|
struct PendingHit
|
|
|
|
|
{
|
|
|
|
|
public Vector2 pos, dir;
|
|
|
|
|
public float energy, radius, obliquity, spin;
|
|
|
|
|
public FracturePattern pattern;
|
|
|
|
|
public float starArms, focus, twist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly Queue<PendingHit> pending = new();
|
|
|
|
|
|
|
|
|
|
TilingData data;
|
|
|
|
|
Material mat;
|
|
|
|
|
MaterialPropertyBlock mpb;
|
|
|
|
|
|
|
|
|
|
GraphicsBuffer bCells, bVerts, bEdges, bState;
|
|
|
|
|
GraphicsBuffer bUA, bUB, bV, bEcho, bFlow, bVisible, bBudget;
|
|
|
|
|
GraphicsBuffer argsFill;
|
|
|
|
|
|
|
|
|
|
bool uUsingA = true;
|
|
|
|
|
int kInit, kInject, kWave, kEcho, kFracture, kUpdate;
|
|
|
|
|
int groups, echoSlot;
|
|
|
|
|
float simTime;
|
|
|
|
|
Bounds worldBounds;
|
|
|
|
|
uint[] budgetScratch; // cached to avoid a per-frame allocation (D12)
|
|
|
|
|
|
2026-09-18 13:51:11 +02:00
|
|
|
// D17/D20 (Cut 3, docs/shield-panel-cut.md): the panel's own arm instant, backdated by
|
|
|
|
|
// one growDuration so a cell at the strike centre (spawnDelay ~= 0) is already past the
|
|
|
|
|
// KInject/KWaveStep/KFracture growth gate the moment it is struck. See ResetSim.
|
|
|
|
|
float panelSpawnTime;
|
|
|
|
|
CellState[] growthSeed; // cached per-cell arm state; rebuilt only when the tiling is (re)built,
|
|
|
|
|
// re-uploaded (not reallocated) on every ResetSim — no interception allocation.
|
|
|
|
|
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
const int EchoSlots = 16;
|
|
|
|
|
static readonly int MaxV = Limits.MaxVerts;
|
|
|
|
|
|
|
|
|
|
// shader ids
|
|
|
|
|
static readonly int idCells = Shader.PropertyToID("_Cells");
|
|
|
|
|
static readonly int idVerts = Shader.PropertyToID("_Verts");
|
|
|
|
|
static readonly int idEdges = Shader.PropertyToID("_Edges");
|
|
|
|
|
static readonly int idState = Shader.PropertyToID("_State");
|
|
|
|
|
static readonly int idUIn = Shader.PropertyToID("_UIn");
|
|
|
|
|
static readonly int idUOut = Shader.PropertyToID("_UOut");
|
|
|
|
|
static readonly int idU = Shader.PropertyToID("_U");
|
|
|
|
|
static readonly int idV = Shader.PropertyToID("_V");
|
|
|
|
|
static readonly int idEcho = Shader.PropertyToID("_Echo");
|
|
|
|
|
static readonly int idFlow = Shader.PropertyToID("_EdgeFlow");
|
|
|
|
|
static readonly int idVisible = Shader.PropertyToID("_Visible");
|
|
|
|
|
static readonly int idBudget = Shader.PropertyToID("_BreakBudget");
|
|
|
|
|
|
|
|
|
|
// ==============================================================
|
2026-09-18 13:51:11 +02:00
|
|
|
// Cut 3 (docs/shield-panel-cut.md §2.4): a pooled panel is SetActive(false)/(true) every
|
|
|
|
|
// time it is returned to and taken back out of Assets/Scripts/Prototype.cs's pool, which
|
|
|
|
|
// fires OnDisable/OnEnable on every reuse, not just once at load. The pool's entire reason
|
|
|
|
|
// for existing is that a rebuild is 1.3-21 ms and a ResetSim is 8-11 us (§2.4); OnEnable
|
|
|
|
|
// unconditionally rebuilding and OnDisable unconditionally releasing would pay the
|
|
|
|
|
// expensive path on every single interception, silently defeating the pool. So the tiling
|
|
|
|
|
// and buffers are built once (guarded by `data == null`) and released only when the
|
|
|
|
|
// GameObject is actually destroyed, not merely deactivated -- ShieldInterceptor.ResetSim()
|
|
|
|
|
// is what re-arms a reused instance (see ResetSim below), not OnEnable.
|
|
|
|
|
void OnEnable() { if (data == null) Rebuild(); }
|
|
|
|
|
void OnDisable() { }
|
|
|
|
|
void OnDestroy() { ReleaseAll(); }
|
|
|
|
|
|
|
|
|
|
// Cut 3 verification surface: counts real tiling builds so the pooling fix (OnEnable only
|
|
|
|
|
// rebuilds when data == null) can be pinned against a regression that rebuilds on every
|
|
|
|
|
// pooled reuse (see ShieldPanelCut3Verify.CheckPoolReuseDoesNotRebuild).
|
|
|
|
|
public int DebugRebuildCount { get; private set; }
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
|
|
|
|
|
[UnityEngine.ContextMenu("Rebuild")]
|
|
|
|
|
public void Rebuild()
|
|
|
|
|
{
|
2026-09-18 13:51:11 +02:00
|
|
|
DebugRebuildCount++;
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
ReleaseAll();
|
|
|
|
|
if (sim == null || panelShader == null) return;
|
|
|
|
|
|
|
|
|
|
var soup = Tilings.Generate(tiling, panelRadius, cellSize, seed);
|
|
|
|
|
|
|
|
|
|
if (tiling == TilingKind.PenroseP3 && mergeRhombs)
|
|
|
|
|
soup = TilingBuilder.MergeRhombs(soup);
|
|
|
|
|
if (takeDual)
|
|
|
|
|
soup = TilingBuilder.TakeDual(soup);
|
|
|
|
|
|
|
|
|
|
data = TilingBuilder.Build(soup,
|
|
|
|
|
weldEps: Mathf.Max(cellSize * 0.02f, 1e-4f),
|
|
|
|
|
clipRadius: panelRadius,
|
|
|
|
|
wavefrontOrigin: Vector2.zero,
|
|
|
|
|
wavefrontSpeed: wavefrontSpeed,
|
|
|
|
|
delayJitter: delayJitter,
|
|
|
|
|
seed: seed);
|
|
|
|
|
|
|
|
|
|
AllocateBuffers();
|
|
|
|
|
CacheKernels();
|
|
|
|
|
ResetSim();
|
|
|
|
|
CheckCfl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AllocateBuffers()
|
|
|
|
|
{
|
|
|
|
|
int n = data.CellCount;
|
|
|
|
|
groups = Mathf.CeilToInt(n / 64f);
|
|
|
|
|
|
|
|
|
|
bCells = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n, CellStatic.Stride);
|
|
|
|
|
bVerts = new GraphicsBuffer(GraphicsBuffer.Target.Structured, data.verts.Length, sizeof(float) * 2);
|
|
|
|
|
bEdges = new GraphicsBuffer(GraphicsBuffer.Target.Structured, Mathf.Max(data.EdgeCount, 1), DualEdge.Stride);
|
2026-09-18 13:51:11 +02:00
|
|
|
bState = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n, CellState.Stride);
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
|
|
|
|
|
bUA = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n, sizeof(float));
|
|
|
|
|
bUB = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n, sizeof(float));
|
|
|
|
|
bV = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n, sizeof(float));
|
|
|
|
|
bEcho = new GraphicsBuffer(GraphicsBuffer.Target.Structured, n * EchoSlots, sizeof(float));
|
|
|
|
|
bFlow = new GraphicsBuffer(GraphicsBuffer.Target.Structured, Mathf.Max(data.EdgeCount, 1), sizeof(float));
|
|
|
|
|
bBudget = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 2, sizeof(uint));
|
|
|
|
|
|
|
|
|
|
bVisible = new GraphicsBuffer(GraphicsBuffer.Target.Append | GraphicsBuffer.Target.Structured,
|
|
|
|
|
n, sizeof(uint));
|
|
|
|
|
|
|
|
|
|
bCells.SetData(data.cells);
|
|
|
|
|
bVerts.SetData(data.verts);
|
|
|
|
|
if (data.EdgeCount > 0) bEdges.SetData(data.dualEdges);
|
|
|
|
|
|
|
|
|
|
// One args buffer, sized to the widest pass (Outline: n*2 segments * 6 verts).
|
|
|
|
|
// RenderParams exposes no per-pass selector in 6000.3.24f1 (D2), and a multi-pass material
|
|
|
|
|
// draws every pass from one indirect call anyway (D5/§2.1.4-5), so the three
|
|
|
|
|
// per-pass buffers this shipped with were dead weight, not three draw paths.
|
|
|
|
|
argsFill = MakeArgs((uint)(MaxV * 2 * 6));
|
|
|
|
|
|
|
|
|
|
mat = new Material(panelShader) { hideFlags = HideFlags.DontSave };
|
|
|
|
|
mpb = new MaterialPropertyBlock();
|
|
|
|
|
|
|
|
|
|
var b = data.bounds;
|
|
|
|
|
float pad = panelRadius * 1.5f + shardLife * 3f;
|
|
|
|
|
worldBounds = new Bounds(transform.TransformPoint(b.center),
|
|
|
|
|
b.size + Vector3.one * pad);
|
|
|
|
|
|
|
|
|
|
budgetScratch ??= new uint[2];
|
2026-09-18 13:51:11 +02:00
|
|
|
BuildGrowthSeed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// D17/D20: precompute the arm-time CellState for every cell once per tiling build, keyed
|
|
|
|
|
// only on each cell's baked `spawnDelay` (TilingBuilder.cs, itself derived from the
|
|
|
|
|
// wavefrontOrigin the tiling was built with -- always the panel centre, per Cut 1's note
|
|
|
|
|
// that one tiling serves every panel). ResetSim re-uploads this same array on every arm/
|
|
|
|
|
// reuse; nothing here runs at interception time (§3's "no allocation at interception").
|
|
|
|
|
void BuildGrowthSeed()
|
|
|
|
|
{
|
|
|
|
|
growthSeed ??= new CellState[data.CellCount];
|
|
|
|
|
if (growthSeed.Length != data.CellCount) growthSeed = new CellState[data.CellCount];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < growthSeed.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
growthSeed[i] = default;
|
|
|
|
|
growthSeed[i].breakTime = -1f;
|
|
|
|
|
growthSeed[i].temper = temperInit;
|
|
|
|
|
// Backdate the arm instant by one growDuration (panelSpawnTime, set alongside this
|
|
|
|
|
// in ResetSim) so a cell with spawnDelay ~= 0 -- the strike centre -- reads as
|
|
|
|
|
// already past the 0.6 growth gate the instant it is struck, while a cell whose
|
|
|
|
|
// baked spawnDelay is >= growDuration starts at 0 and grows forward normally as
|
|
|
|
|
// simTime advances past panelSpawnTime. This is what fixes D17 (the growth gate
|
|
|
|
|
// otherwise swallows the hit that created the panel, because KUpdate -- the only
|
|
|
|
|
// writer of `growth` -- does not run until after this same frame's KInject) without
|
|
|
|
|
// touching the gate itself or adding a per-interception dispatch.
|
|
|
|
|
growthSeed[i].growth = Mathf.Clamp01(
|
|
|
|
|
(growDuration - data.cells[i].spawnDelay) / Mathf.Max(growDuration, 1e-3f));
|
|
|
|
|
}
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GraphicsBuffer MakeArgs(uint vertsPerInstance)
|
|
|
|
|
{
|
|
|
|
|
var a = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1,
|
|
|
|
|
GraphicsBuffer.IndirectDrawArgs.size);
|
|
|
|
|
a.SetData(new[] { new GraphicsBuffer.IndirectDrawArgs {
|
|
|
|
|
vertexCountPerInstance = vertsPerInstance,
|
|
|
|
|
instanceCount = 0, startVertex = 0, startInstance = 0 } });
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CacheKernels()
|
|
|
|
|
{
|
|
|
|
|
kInit = sim.FindKernel("KInit");
|
|
|
|
|
kInject = sim.FindKernel("KInject");
|
|
|
|
|
kWave = sim.FindKernel("KWaveStep");
|
|
|
|
|
kEcho = sim.FindKernel("KEcho");
|
|
|
|
|
kFracture = sim.FindKernel("KFracture");
|
|
|
|
|
kUpdate = sim.FindKernel("KUpdate");
|
|
|
|
|
|
|
|
|
|
foreach (int k in new[] { kInit, kInject, kWave, kEcho, kFracture, kUpdate })
|
|
|
|
|
{
|
|
|
|
|
sim.SetBuffer(k, idCells, bCells);
|
|
|
|
|
sim.SetBuffer(k, idEdges, bEdges);
|
|
|
|
|
sim.SetBuffer(k, idState, bState);
|
|
|
|
|
sim.SetBuffer(k, idV, bV);
|
|
|
|
|
sim.SetBuffer(k, idEcho, bEcho);
|
|
|
|
|
sim.SetBuffer(k, idFlow, bFlow);
|
|
|
|
|
sim.SetBuffer(k, idBudget, bBudget);
|
|
|
|
|
}
|
|
|
|
|
sim.SetBuffer(kInit, idUOut, bUA);
|
|
|
|
|
sim.SetBuffer(kWave, idFlow, bFlow);
|
|
|
|
|
sim.SetBuffer(kUpdate, idVisible, bVisible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[UnityEngine.ContextMenu("Reset Simulation")]
|
|
|
|
|
public void ResetSim()
|
|
|
|
|
{
|
2026-09-18 13:51:11 +02:00
|
|
|
// Cut 3: a freshly-instantiated pool instance's OnEnable is not guaranteed to have run
|
|
|
|
|
// by the time the interceptor calls ResetSim() on it in the same call stack (observed in
|
|
|
|
|
// the batchmode probe: Object.Instantiate's Awake/OnEnable are not synchronous with the
|
|
|
|
|
// call that created the clone in every context this runs in). ResetSim is what every
|
|
|
|
|
// spawn and reuse already goes through, so it -- not OnEnable's timing -- is what
|
|
|
|
|
// guarantees "built before struck". This costs nothing on the pooled-reuse path that
|
|
|
|
|
// §2.4's budget is about: data is already non-null there, so this is one null check, not
|
|
|
|
|
// a second rebuild.
|
|
|
|
|
if (data == null) { Rebuild(); return; } // Rebuild() ends by calling ResetSim() itself
|
|
|
|
|
if (sim == null) return;
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
simTime = 0f;
|
|
|
|
|
echoSlot = 0;
|
|
|
|
|
uUsingA = true;
|
|
|
|
|
pending.Clear();
|
|
|
|
|
|
|
|
|
|
sim.SetInt("_CellCount", data.CellCount);
|
|
|
|
|
sim.SetFloat("_TemperInit", temperInit);
|
|
|
|
|
sim.SetBuffer(kInit, idUOut, bUA);
|
|
|
|
|
sim.Dispatch(kInit, groups, 1, 1);
|
|
|
|
|
|
|
|
|
|
// second clear so both halves of the ping-pong start at rest
|
|
|
|
|
sim.SetBuffer(kInit, idUOut, bUB);
|
|
|
|
|
sim.Dispatch(kInit, groups, 1, 1);
|
|
|
|
|
sim.SetBuffer(kInit, idUOut, bUA);
|
2026-09-18 13:51:11 +02:00
|
|
|
|
|
|
|
|
// D17/D20: KInit above just zeroed every cell's `growth` (and this panel's own local
|
|
|
|
|
// clock, simTime, back to 0). Overwrite with the precomputed arm-time state instead of
|
|
|
|
|
// leaving it at 0 -- see BuildGrowthSeed's comment for why waiting on KUpdate to catch
|
|
|
|
|
// up is one frame too late for a hit queued this same call. `growDuration` may have
|
|
|
|
|
// changed in the inspector since the seed was built, but recomputing it here would be a
|
|
|
|
|
// per-arm allocation-shaped cost the pool's 8-11 us budget (§2.4) has no room for;
|
|
|
|
|
// Rebuild (a manual, non-pooled action) is what re-derives the seed from authored
|
|
|
|
|
// fields, matching CheckCfl's existing must-Rebuild-to-see-it contract.
|
|
|
|
|
panelSpawnTime = -growDuration;
|
|
|
|
|
bState.SetData(growthSeed);
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CheckCfl()
|
|
|
|
|
{
|
|
|
|
|
float minArea = float.MaxValue;
|
|
|
|
|
int maxDeg = 0;
|
|
|
|
|
foreach (var c in data.cells)
|
|
|
|
|
{
|
|
|
|
|
minArea = Mathf.Min(minArea, c.area);
|
|
|
|
|
maxDeg = Mathf.Max(maxDeg, (int)c.nbrCount);
|
|
|
|
|
}
|
|
|
|
|
// rough stability bound for the explicit leapfrog on an irregular graph
|
|
|
|
|
float lim = waveSpeed2 * fixedSubstepDt * fixedSubstepDt * maxDeg / Mathf.Max(minArea, 1e-6f);
|
|
|
|
|
if (lim > 1.8f)
|
|
|
|
|
Debug.LogWarning($"[ShieldPanel] CFL estimate {lim:F2} exceeds ~1.8 and the wave " +
|
|
|
|
|
$"will likely diverge. Lower waveSpeed2 or fixedSubstepDt, or raise cellSize. " +
|
|
|
|
|
$"(smallest cell area {minArea:E2}, max degree {maxDeg})", this);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-18 13:51:11 +02:00
|
|
|
// ==============================================================
|
|
|
|
|
// Read-only verification surface for the Cut 3 batchmode probe (Tests.asmdef cannot see
|
|
|
|
|
// Assembly-CSharp -- the map's Q7 -- so this, like Cut 1/2's probes, is what stands in for
|
|
|
|
|
// a unit test). Nothing outside ShieldPanel may WRITE these buffers (the authority map's
|
|
|
|
|
// "nothing outside ShieldPanel touches its buffers" is about writers); GraphicsBuffer.
|
|
|
|
|
// GetData is a read.
|
|
|
|
|
public int DebugCellCount => data?.CellCount ?? 0;
|
|
|
|
|
public GraphicsBuffer DebugStateBuffer => bState;
|
|
|
|
|
public GraphicsBuffer DebugVField => bV;
|
|
|
|
|
public Vector2 DebugCellCenter(int i) => data.cells[i].centroid;
|
|
|
|
|
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
// ==============================================================
|
|
|
|
|
/// <summary>Strike the panel. worldDir is the projectile's travel direction.</summary>
|
|
|
|
|
public void Hit(Vector3 worldPos, Vector3 worldDir, float energy,
|
|
|
|
|
FracturePattern pattern = FracturePattern.Radial,
|
|
|
|
|
float radius = -1f)
|
|
|
|
|
{
|
|
|
|
|
if (data == null) return;
|
|
|
|
|
|
|
|
|
|
Vector3 local = transform.InverseTransformPoint(worldPos);
|
|
|
|
|
Vector3 ldir = transform.InverseTransformDirection(worldDir).normalized;
|
|
|
|
|
|
|
|
|
|
Vector2 flat = new Vector2(ldir.x, ldir.y);
|
|
|
|
|
float obliquity = Mathf.Clamp01(1f - Mathf.Abs(ldir.z));
|
|
|
|
|
|
|
|
|
|
pending.Enqueue(new PendingHit
|
|
|
|
|
{
|
|
|
|
|
pos = new Vector2(local.x, local.y),
|
|
|
|
|
dir = flat.sqrMagnitude > 1e-6f ? flat.normalized : Vector2.right,
|
|
|
|
|
energy = energy,
|
|
|
|
|
radius = radius > 0f ? radius : Mathf.Max(cellSize * 2.5f, panelRadius * 0.09f),
|
|
|
|
|
obliquity = obliquity,
|
|
|
|
|
pattern = pattern,
|
|
|
|
|
starArms = Random.Range(3, 9),
|
|
|
|
|
focus = Mathf.Lerp(0.15f, 0.55f, Random.value),
|
|
|
|
|
twist = Random.Range(0.4f, 1.6f),
|
|
|
|
|
spin = Random.value * Mathf.PI * 2f
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==============================================================
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
|
|
|
|
if (sim == null || data == null || mat == null) return;
|
|
|
|
|
|
|
|
|
|
float dt = Application.isPlaying ? Time.deltaTime : 1f / 60f;
|
|
|
|
|
simTime += dt;
|
|
|
|
|
|
|
|
|
|
sim.SetInt("_CellCount", data.CellCount);
|
|
|
|
|
sim.SetFloat("_Time", simTime);
|
|
|
|
|
PushMaterialUniforms();
|
|
|
|
|
|
|
|
|
|
// ---- break budget resets every frame; this is what paces the cascade
|
|
|
|
|
uint cap = (uint)Mathf.Max(1, Mathf.RoundToInt(data.CellCount * breakBudgetFraction));
|
|
|
|
|
budgetScratch[0] = 0u;
|
|
|
|
|
budgetScratch[1] = cap;
|
|
|
|
|
bBudget.SetData(budgetScratch);
|
|
|
|
|
|
|
|
|
|
// ---- inject queued hits
|
|
|
|
|
sim.SetFloat("_Dt", fixedSubstepDt);
|
|
|
|
|
while (pending.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var h = pending.Dequeue();
|
|
|
|
|
sim.SetVector("_HitPos", h.pos);
|
|
|
|
|
sim.SetVector("_HitDir", h.dir);
|
|
|
|
|
sim.SetFloat("_HitEnergy", h.energy);
|
|
|
|
|
sim.SetFloat("_HitRadius", h.radius);
|
|
|
|
|
sim.SetFloat("_HitObliquity", h.obliquity);
|
|
|
|
|
sim.SetInt("_Pattern", (int)h.pattern);
|
|
|
|
|
sim.SetFloat("_StarArms", h.starArms);
|
|
|
|
|
sim.SetFloat("_PatternFocus", h.focus);
|
|
|
|
|
sim.SetFloat("_SpiralTwist", h.twist);
|
|
|
|
|
sim.SetFloat("_HitSpin", h.spin);
|
|
|
|
|
sim.SetInt("_EchoSlot", echoSlot);
|
|
|
|
|
sim.SetBuffer(kInject, idV, bV);
|
|
|
|
|
sim.Dispatch(kInject, groups, 1, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- wave substeps (fixed dt: the CFL limit does not care about frame rate)
|
|
|
|
|
sim.SetFloat("_WaveSpeed2", waveSpeed2);
|
|
|
|
|
sim.SetFloat("_Damping", damping);
|
|
|
|
|
sim.SetFloat("_StressClamp", stressClamp);
|
|
|
|
|
sim.SetInt("_EchoDelay", echoDelaySteps);
|
|
|
|
|
sim.SetFloat("_EchoReflect", echoReflect);
|
|
|
|
|
|
|
|
|
|
for (int s = 0; s < substeps; s++)
|
|
|
|
|
{
|
|
|
|
|
var src = uUsingA ? bUA : bUB;
|
|
|
|
|
var dst = uUsingA ? bUB : bUA;
|
|
|
|
|
|
|
|
|
|
sim.SetBuffer(kWave, idUIn, src);
|
|
|
|
|
sim.SetBuffer(kWave, idUOut, dst);
|
|
|
|
|
sim.Dispatch(kWave, groups, 1, 1);
|
|
|
|
|
uUsingA = !uUsingA;
|
|
|
|
|
|
|
|
|
|
sim.SetInt("_EchoSlot", echoSlot);
|
|
|
|
|
sim.Dispatch(kEcho, groups, 1, 1);
|
|
|
|
|
echoSlot = (echoSlot + 1) % EchoSlots;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cur = uUsingA ? bUA : bUB;
|
|
|
|
|
|
|
|
|
|
// ---- fracture
|
|
|
|
|
sim.SetFloat("_TensileStrength", tensileStrength);
|
|
|
|
|
sim.SetFloat("_TemperErosion", temperErosion);
|
|
|
|
|
sim.SetFloat("_StoredEnergyGain", storedEnergyGain);
|
|
|
|
|
sim.SetFloat("_DamageGain", damageGain);
|
|
|
|
|
sim.SetFloat("_BreakAt", breakAt);
|
|
|
|
|
sim.SetFloat("_CrackStart", crackStart);
|
|
|
|
|
sim.SetFloat("_RadialKick", radialKick);
|
|
|
|
|
sim.SetFloat("_LateralKick", lateralKick);
|
|
|
|
|
sim.SetFloat("_NormalKick", normalKick);
|
|
|
|
|
sim.SetFloat("_SpinKick", spinKick);
|
|
|
|
|
sim.SetBuffer(kFracture, idUIn, cur);
|
|
|
|
|
sim.Dispatch(kFracture, groups, 1, 1);
|
|
|
|
|
|
|
|
|
|
// ---- per-frame state advance + visibility
|
|
|
|
|
sim.SetFloat("_Dt", dt);
|
2026-09-18 13:51:11 +02:00
|
|
|
sim.SetFloat("_PanelSpawnTime", panelSpawnTime);
|
Land the six shield-panel sources, ported to built-in and compiling
Cut 1 of docs/shield-panel-cut.md: land ShieldPanel.cs, ShieldPanel.shader,
ShieldSim.compute, ShieldCommon.hlsl, TilingBuilder.cs and Tilings.cs under
Assets/Shaders/Compute/ShieldField/, alongside Lightning/ and Slime/.
Port (URP -> built-in, three substitutions per the map's §2.1 probe):
- drop the UniversalPipeline SubShader tag, add IgnoreProjector
- swap the URP Core.hlsl include for UnityCG.cginc
- TransformWorldToHClip -> UnityWorldToClipPos (3 call sites)
Drawing collapse (D2/D5): RenderParams has no shaderPass member in
6000.3.24f1, and a multi-pass material draws every SubShader pass from one
indirect call regardless, so the three per-pass args buffers and draw calls
collapse to one args buffer sized to the widest pass (Outline) and one
Graphics.RenderPrimitivesIndirect call. Deleted: argsOutline, argsConduit,
drawFill/drawOutline/drawConduits and their branches.
Also deleted: ShieldPanelTester (the click harness the operator ruled
against; it also can't run — activeInputHandler is New Input System only)
and [ExecuteAlways] (incompatible with a pool per D13; Rebuild stays on the
context menu).
Defects fixed:
- D1: TilingBuilder.cs's inner `dist` shadowed the outer one (CS0136);
renamed to nbrDist.
- D3: CellStatic was 15 floats against a declared Stride of 16; added pad2
on both the HLSL and C# sides.
- D4: `centroid` is reserved in the compute compiler; renamed the
ShieldCommon.hlsl field to `center` (kept the C# field name as-is; it's
not reserved there and the two sides don't need matching names, only
matching layout).
- D6: fixed the comment on _BreakBudget — it's two elements (count + cap),
not the "single element" the old comment claimed.
- D12: the two-element uint[] Update() allocated every frame is now a
cached field, cheaper still under a pool of many live panels.
- D18 (R5 — operator ruling, not deferred to a follow-up): Penrose ignored
panelRadius entirely — a fixed authored iteration count meant the tiling
was just uniformly rescaled, not resampled, so cell count never grew with
the panel. Every other tiling here uses cellSize to hold local cell size
constant while radius extends coverage; Penrose now derives its iteration
count the same way (each substitution divides edge length by phi, solved
for the count that brings a unit edge to ~cellSize once scaled to
radius). This retires the now-meaningless `penroseIterations` field and
the `subdivisions` parameter it threaded through Tilings.Generate.
- Also removed a dead `idx` counter in Tilings.Voronoi (D8's mention of
dead code; the Vector2.zero sentinel ambiguity itself is unfixed, same as
D7/D19 — Voronoi and TriHex stay recorded defects, not fixed, per R5).
Not fixed here, per the map: D7 (Voronoi is unusably slow) and D19 (TriHex
has zero dual edges) are recorded, not fixed. D9/D10 (fracture tuning) are
Cut 5. D17 (growth gate blocks the spawning hit) and D20 (_PanelSpawnTime
hardcoded to 0) are Cut 3.
Repo-specific fix not in the map: Assets/Scripts/UI/ContextMenu.cs defines
a global `ContextMenu` MonoBehaviour that shadows UnityEngine.ContextMenu,
so `[ContextMenu("Rebuild")]` doesn't compile here (CS0616) even though it
did in the map's throwaway probe project. Used the fully-qualified
`[UnityEngine.ContextMenu(...)]` instead.
Adds Assets/Scripts/Editor/ShieldPanelCut1Verify.cs, a batchmode probe (no
NUnit path exists per the map's Q7 — Tests.asmdef can't see
Assembly-CSharp): asserts zero shader/compute compile errors and that
Penrose cell count actually scales with panelRadius (D18). Also adds
tests/mutation_tests_shield_panel_cut1.py, which mutates the D18 fix, the
D4 fix, and the shaderPass deletion in turn and asserts the probe goes red
each time, restoring the source after each case (own file per the
convention mutation_tests_addressables_cut.py established, so as not to
touch item-provenance's or the addressables cut's harnesses).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 06:08:04 +02:00
|
|
|
sim.SetFloat("_GrowDuration", growDuration);
|
|
|
|
|
sim.SetFloat("_GlowDecay", 3.2f);
|
|
|
|
|
sim.SetFloat("_ShardLife", shardLife);
|
|
|
|
|
sim.SetFloat("_ShardDrag", shardDrag);
|
|
|
|
|
|
|
|
|
|
bVisible.SetCounterValue(0);
|
|
|
|
|
sim.Dispatch(kUpdate, groups, 1, 1);
|
|
|
|
|
|
|
|
|
|
GraphicsBuffer.CopyCount(bVisible, argsFill, sizeof(uint));
|
|
|
|
|
|
|
|
|
|
Draw(cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PushMaterialUniforms()
|
|
|
|
|
{
|
|
|
|
|
mat.SetFloat("_CrackStart", crackStart);
|
|
|
|
|
mat.SetFloat("_ShardLife", shardLife);
|
|
|
|
|
mat.SetInt("_MaxShards", maxShards);
|
|
|
|
|
mat.SetFloat("_ConduitGain", conduitGain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Draw(GraphicsBuffer curU)
|
|
|
|
|
{
|
|
|
|
|
mpb.Clear();
|
|
|
|
|
mpb.SetBuffer(idCells, bCells);
|
|
|
|
|
mpb.SetBuffer(idVerts, bVerts);
|
|
|
|
|
mpb.SetBuffer(idEdges, bEdges);
|
|
|
|
|
mpb.SetBuffer(idState, bState);
|
|
|
|
|
mpb.SetBuffer(idU, curU);
|
|
|
|
|
mpb.SetBuffer(idFlow, bFlow);
|
|
|
|
|
mpb.SetBuffer(idVisible, bVisible);
|
|
|
|
|
mpb.SetMatrix("_PanelToWorld", transform.localToWorldMatrix);
|
|
|
|
|
mpb.SetFloat("_Time01", simTime);
|
|
|
|
|
|
|
|
|
|
worldBounds.center = transform.position;
|
|
|
|
|
|
|
|
|
|
var rp = new RenderParams(mat)
|
|
|
|
|
{
|
|
|
|
|
worldBounds = worldBounds,
|
|
|
|
|
matProps = mpb,
|
|
|
|
|
shadowCastingMode = ShadowCastingMode.Off,
|
|
|
|
|
receiveShadows = false,
|
|
|
|
|
layer = gameObject.layer
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// RenderParams exposes no per-pass selector in 6000.3.24f1 (D2), and a multi-pass
|
|
|
|
|
// material draws every SubShader pass from one indirect call regardless
|
|
|
|
|
// (D5) — Fill, Outline and Conduit all run here, pixel-identical to the
|
|
|
|
|
// old three-call version (§2.1.5), off one args buffer sized to the
|
|
|
|
|
// widest pass (Outline).
|
|
|
|
|
Graphics.RenderPrimitivesIndirect(rp, MeshTopology.Triangles, argsFill, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==============================================================
|
|
|
|
|
void ReleaseAll()
|
|
|
|
|
{
|
|
|
|
|
void R(ref GraphicsBuffer b) { b?.Release(); b = null; }
|
|
|
|
|
R(ref bCells); R(ref bVerts); R(ref bEdges); R(ref bState);
|
|
|
|
|
R(ref bUA); R(ref bUB); R(ref bV); R(ref bEcho); R(ref bFlow);
|
|
|
|
|
R(ref bVisible); R(ref bBudget);
|
|
|
|
|
R(ref argsFill);
|
|
|
|
|
|
|
|
|
|
if (mat != null)
|
|
|
|
|
{
|
|
|
|
|
if (Application.isPlaying) Destroy(mat); else DestroyImmediate(mat);
|
|
|
|
|
mat = null;
|
|
|
|
|
}
|
|
|
|
|
data = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnDrawGizmosSelected()
|
|
|
|
|
{
|
|
|
|
|
Gizmos.color = new Color(0.4f, 0.8f, 1f, 0.5f);
|
|
|
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
|
|
|
Gizmos.DrawWireSphere(Vector3.zero, panelRadius);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|