public readonly record struct UiShapeEverything the box shader needs about one box, in the layout it reads.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
⚠ Per box, not per vertex, and that is the whole reason this type exists. Four corners with an elliptical radius each is eight floats, a three-stop gradient is another fifteen, and a box is four vertices — so carrying them on the vertex would take it from forty-eight bytes to well past a hundred, and every glyph and every path triangle in the frame would pay for fields no shader reads on them. One record per box costs a hundred and sixty bytes against the sixty-four the four vertices already spend on Shape, and the vertex layout does not move at all: a box's Shape.X becomes the index of its record.
⚠ Ten Vector4s, written out rather than left to a struct layout to work out. This is copied into a storage buffer with MemoryMarshal and read back by a shader whose own alignment rules are not C#'s — a float beside a Vector2 lays out differently under std430 than under sequential, and the failure is a box drawn with another box's radii, which looks like a bug in the geometry.
⚠ Several files have to agree about this layout, and half of them are invisible to a search for this type's name. The ones that name it: this record, Platform/Vixen.Ui.Desktop/Shaders/Ui.rvn, the committed UiBox.frag.spv and UiBox.reflect.json beside it, and SoftwareUiRasterizer. The ones that do not: UiRenderer, which needs only the size and once spelled it 80 in three places; and one hand-maintained GLSL copy of the box shader, under Vixen.Graphics.Golden.Tests, which calls the struct Shape. There were three GLSL copies until the sample and the vixen-app template stopped carrying their own frame loops, and two Raven ones until Vixen.Editor.Host's duplicate of Ui.rvn was deleted — so what is left is one source, named and checked rather than transcribed.
⚠ Which test covers which half is worth knowing before changing this. UiShapeLayoutTests pins the record's shape against the committed reflection beside Platform/Vixen.Ui.Desktop/Shaders/Ui.rvn and has nothing to say about how a host sizes a buffer around it; ./build.sh CheckShaders pins the Raven source against its modules and does not see GLSL. The stride and the GLSL copy are caught only by Vixen.Graphics.Golden.Tests, on a real device — which is exactly what caught them when this record grew. UiRenderer now derives its stride from Marshal.SizeOf, so that one cannot drift again; the GLSL still can.
⚠ Every lane this record has ever grown was appended, and the two repurposed ones were both zero. Growing from eighty bytes to a hundred and twelve, then to a hundred and forty-four and then to a hundred and sixty, left every existing offset exactly where the shader already read it: Axis.w was declared padding and is now the interpolation space, whose zero is Linear — which is what the shader did before there was a choice — and Size.w was a zero-or-one gradient flag and is now the shape, whose one is Linear, which is what a flag set to one meant. That is not a coincidence to admire; it is a hazard to name. A stale shader reading this record still draws two-stop linear gradients correctly and silently ignores everything below offset eighty, so drift here does not announce itself as garbage on screen. The test is the only thing that finds it.
Fields and properties (10)
public Vector4 SizeHalf width, half height, border thickness, and which family of gradient.
public Vector4 RadiiXThe four horizontal radii, clockwise from the top left.
public Vector4 RadiiYThe four vertical radii, in the same order.
public Vector4 AxisThe gradient's direction, then a shadow's blur radius, then the interpolation space.
public Vector4 EndThe colour at the last stop.
public Vector4 MidThe colour at the middle stop, read only when Stops's last lane is set.
public Vector4 StopsWhere the three stops sit, then whether the middle one exists.
public Vector4 PaintThe ramp's own centre, then how far it reaches. A zero reach means the box.
public Vector4 AreaThe first tile's centre, then half its size with background-repeat in the sign. All zero means the tile is the box.
public Vector4 InsetAn inset shadow's offset and spread, then whether it is one at all. All zero is every box and every outer shadow.
Methods (2)
public UiShape(Vector2 half, float thickness, CornerRadii corners, Color4 gradientEnd, Vector2 gradientAxis, float blur = 0)Creates a shape record for a flat fill or a plain two-stop linear gradient.
public UiShape(Vector2 half, float thickness, CornerRadii corners, GradientShape shape, GradientSpace space, Vector2 gradientAxis, Color4 gradientEnd, Color4 gradientVia, bool hasVia, GradientStops stops, float blur = 0, Vector2 paintCentre = default(Vector2), Vector2 paintExtent = default(Vector2), Vector2 areaCentre = default(Vector2), Vector2 areaHalf = default(Vector2), bool inset = false, Vector2 insetOffset = default(Vector2), float insetSpread = 0)Creates a shape record for any gradient this shader draws.
Used by (7)
- SoftwareUiRasterizerVixen.Ui.Testing
- UiGamutTestsVixen.Ui.Tests
- UiGeometryVixen.Ui
- UiGeometryBuilderVixen.Ui
- UiGeometryTestsVixen.Ui.Tests
- UiRendererVixen.Ui.Renderer
- UiShapeLayoutTestsVixen.Ui.Tests