Skip to content

Grass definitions and pivots

Vegetation includes ordinary FLVER meshes with pivot attributes as well as Elden Ring’s separate SpeedTree streams. Pivot members give a deformation origin in model space, rather than another texture-coordinate set. Observed

Sekiro pivot families include Translucency_Pivot, Pivot_Parent and snake_Pivot. Elden Ring grass, tree and Vesitation families also store Half4 pivots, transformed by their vertex programs as positions. See vertex formats. Observed

A map piece or asset that grows grass carries a .grass file beside its model (member id 1200 of its .mapbnd or .geombnd binder): 772 files in Sekiro and 1,925 in Elden Ring. Proven · every .mapbnd and .geombnd binder of both installs It is a triangle mesh in the model’s space whose vertices each store six densities, one for each grass type the part’s grass configuration names, and a binary tree of volumes over the triangles. It holds no blade: where blades stand is not stored. Inferred The file is little-endian and its tables fill it exactly: a 40-byte header, the volumes, the vertices, the faces and the boxes. Proven · all 2,697 files

Grass mesh header40 bytes100% known

The record sizes and the box count are constant.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04u32 = 1versionProven
0x44u32 = 40header sizeProven
0x84u32 = 20volume sizeProven
0xC4u32volume countProven
0x104u32 = 36vertex sizeProven
0x144u32vertex countProven
0x184u32 = 24face sizeProven
0x1C4u32face countProven
0x204u32 = 24box sizeProven
0x244u32box countProvenEqual to the volume count
Grass volume20 bytes100% known

A binary tree, the root first.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04u32first childProvenIndex of a volume after this one, 0 for none
0x44u32second childProvenAs the first child
0x84u32first faceProvenThe faces under the volume run from here
0xC4u32end faceProvenTo here, exclusive
0x104u32grass typesProvenA bit for each of the six types a vertex of one of its faces grows
Grass vertex36 bytes33% known
ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x012f32[3]positionProven
0xC24f32[6]densitiesInferredOne for each grass type; 0 to 1
Grass face24 bytes100% known
ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x012f32[3]normalObservedAgainst the cross product of the edges; not always a unit vector
0xC12u32[3]vertex indicesProven

Each box (24 bytes, after the faces, one per volume in volume order) is a least and a greatest corner as six floats; the box of a volume holds every vertex of the faces under it. Proven · all 2,697 files The community’s reader names the volume’s first four words a child range and a face range; the files show that the first two are the indices of the volume’s two children (one child on 242 volumes of Sekiro and 19 of Elden Ring, none on a leaf), and that the fifth, which that reader leaves unnamed, is the set of grass types. Proven · all 2,697 files

In every file the volumes form one tree from volume 0: each child comes after its parent and has one parent, a child’s faces are within its parent’s, and the root holds every face. Proven · all 2,697 files A volume with two children (7,165 in Sekiro, 43,954 in Elden Ring) holds exactly their faces, the two ranges abutting; a volume with one child (242 and 19) holds more than its child does. Proven · all 2,697 files

The densities are in 0 to 1 and do not sum to one per vertex: 284,661 of Sekiro’s 723,967 vertices and 1,169,828 of Elden Ring’s 4,490,801 sum to more than one, and 133,503 and 574,942 have no type at all. Proven · all 2,697 files The stored face normal points against the right-hand cross product of the face’s edges from its first vertex (cosine below -0.999 on 1,064,757 of Sekiro’s 1,065,442 faces and 7,797,867 of Elden Ring’s 7,799,267; 532 and 674 faces store none), but it has unit length on only 88% and 94% of them (0.1 to 5 on the rest); what the length stands for is not known. Observed

Map-part grass configuration names six GrassTypeParam row IDs. Those rows name the detailed and simplified models and flat or billboard textures, with density, spacing and LOD range. Reading references in m10_00_00_00, m12_02_00_00 and m60_39_54_00 checks this resolution against regulation.bin; it does not establish blade placement. Observed · Elden Ring

GrassTypeParam resource fields276 bytesElden Ring0% known

Selected fields of the Paramdex layout; unlisted bytes are not described here. Names are fixed-width UTF-16.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x02u16LOD rangeSourced
0x84f32base densitySourced
0xC32UTF-16model0 nameSourced
0x2C64UTF-16flat texture nameSourced
0x6C64UTF-16billboard texture nameSourced
0xCC4f32spacingSourced
0xD432UTF-16simple model nameSourced
0xF432UTF-16model1 nameSourced

Empty resource-name fields denote no named resource. The resource-field layout requires at least 276 bytes; this partial description does not assign meanings to the intervening fields or any appended bytes. Sourced · Elden Ring · Paramdex

A frame at the Stormveil gate holds two kinds of grass draw. Placed grass models (the AEG210 asset family, Grass_ and Grass2_ G-buffer programs) are ordinary one-instance indexed draws of 534 to 68,871 indices. Further away, Grass2_LOD1 programs draw two tiny meshes (14 and 4 triangles) as GPU instances, 160 to 315 to a draw, from the draw’s cbInstanceData records: 315 is what its 65,536-byte range holds of 208-byte records. Observed · Elden Ring · one frame The records are written by the CPU each frame; a record is a 3×4 world matrix (translation in the fourth column), a fade alpha, forceNum and forceIndex and a colour palette, the layout of every instanced model of the frame. Observed · Elden Ring · one frame That these clumps are the blades the grass configuration places is likely and not shown: no frame says which GrassTypeParam row made them. Inferred

Placement in that frame, over the 825 clumps of the three draws of the larger mesh (61 to 129 m from the eye): positions are not on a grid (nearest-neighbour distance 0.15 to 3.6 m, median 0.84 m); the clump count per 8 m square runs from 1 to 83 and falls off smoothly towards the patch edge, so the density varies from place to place by more than the 0.9 to 1.1 scatter of the clumps; heading is uniform over all directions; horizontal scale is 0.9 to 1.1 (0.6 to 1.1 for the smaller mesh) and vertical scale independent of it, 0.55 to 1.2. Draws are batches by distance (61 to 91 m, 91 to 108 m, 105 to 129 m for the larger mesh; 142 to 164 m and 175 to 210 m for the others), 315 clumps at most. Observed · Elden Ring · one frame

The Grass2_LOD1 vertex program declares the structured buffer g_forceParam (ForceParamStruct, 96 bytes: a uint4 SystemParam, then float4 PosAndSquareForce, DirAndSineForce, WindParam, GustParam and GustTimeParam) and the byte buffer g_InstanceIndexBuffer. Observed · Elden Ring · the program’s reflection Its 256 records are filled by a buffer copy from the upload ring early in the frame, and only 8 or 9 are non-zero. Observed · Elden Ring · five frames In five frames at the gate, the non-zero records are the same six at the same positions and directions (in the frame’s local coordinates, for example (-48.1, 48.5, 57.8) with direction (0.899, 0, 0.437)), each with SystemParam (1, 1, 0, 0), GustParam (1, 1, 1, 0), GustTimeParam (3, 5, 10, 60), WindParam.x 1 and WindParam.w 0.1, a per-record WindParam.y (123.8 to 179.6) that does not change between frames, and a WindParam.z shared by the six that grows from frame to frame (155.07, 161.50, 167.91, 169.35, 169.80), 1.696 to 1.698 times the frame clock T of the SpeedTree wind. Observed · Elden Ring · five frames The fourth word of PosAndSquareForce and of DirAndSineForce is one shared number (12.7 to 14.2, a different one in each frame). One to three further records of each frame repeat some of those positions and directions with a WindParam.z of 0.99 and a fourth word near 12.1. Observed · Elden Ring · five frames Two of the five frames also hold a record near the eye, at (3.7, 7.3, 10.0), with direction (-0.579, 0, -0.816), WindParam (0.8, 55.4, ·, 0.3), GustTimeParam.x 2 and a fourth word near 7.3, which the other three frames lack; a force at the player’s place would fit. Inferred Each batch’s instances carry forceNum and a forceIndex (2 and 1283 for the three larger-mesh batches, 1 and 5 for the 142 to 164 m batch, 1 and 1 for the 175 to 210 m one); that forceIndex is a start into the index buffer that names records of g_forceParam is the reading of the names, and the index buffer’s contents at the start of the frame (identity) do not show it. Inferred How a program turns these words into a blade’s motion is in the program’s code and was not read here.

Which GrassTypeParam row does each of the six densities drive?

A part’s grass configuration names six rows and the vertices store six densities; that the order is the same is likely and has not been checked against a rendering. The frames show the result (the clump placement above) but not which row or density a clump came from: that needs the part’s configuration, its .grass file and a frame taken where they are loaded, and the instances’ positions put in the file’s frame. Not done.

How are individual grass blades placed and animated?

Narrowed: in the frames the far grass is a CPU-written set of clumps with random heading and scale, denser where the mesh says so, drawn in distance batches; its motion reads a table of wind and force records per frame whose clock is the SpeedTree frame clock times 1.7. Not known: the seed and the rule that turns density and spacing into positions, how a program uses the record words, and the near grass (the placed Grass_ models), whose blades are in the model.