Skip to content

Expose lod-range-min and lod-range-max attributes on pc-gsplat#254

Merged
willeastcott merged 5 commits into
mainfrom
expose-gsplat-lod-range-attributes
Jun 29, 2026
Merged

Expose lod-range-min and lod-range-max attributes on pc-gsplat#254
willeastcott merged 5 commits into
mainfrom
expose-gsplat-lod-range-attributes

Conversation

@willeastcott

@willeastcott willeastcott commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

Adds two new attributes to the <pc-gsplat> element, completing the LOD control surface that already includes lod-base-distance and lod-multiplier:

Attribute Engine property Default Effect
lod-range-min lodRangeMin 0 Minimum allowed LOD index (inclusive). Clamps the distance-selected LOD so it never goes finer than this. Raising it avoids downloading the largest, highest-quality LOD files.
lod-range-max lodRangeMax 99 Maximum allowed LOD index (inclusive). Clamps the LOD so it never goes coarser than this; default 99 effectively means "no cap".
<pc-gsplat asset="city" lod-range-min="1" lod-range-max="4"></pc-gsplat>

These only affect assets that contain LOD levels (e.g. .lod-meta.json streaming splats).

Why

An audit of GSplatComponent (engine 2.20.0) against the attributes pc-gsplat currently exposes (asset, cast-shadows, lod-base-distance, lod-multiplier) found lodRangeMin/lodRangeMax to be the clean, missing additions — simple numeric properties that complete the LOD authoring story declaratively. Other unexposed properties were considered and left out (workBufferUpdate pairs with the JS-only setWorkBufferModifier(); layers isn't exposed on any other pc-* component; customAabb/resource/id aren't cleanly attribute-expressible; the rest are deprecated/@ignore).

Implementation note for reviewers

The engine's GSplatComponentSystem.initializeComponentData only applies a fixed allow-list of properties (unified, lodBaseDistance, lodMultiplier, castShadows, material, asset, resource, layers) and ignores lodRangeMin/lodRangeMax. Passing them through getInitialComponentData() is therefore silently dropped by the engine. They are instead applied via the existing initComponent() hook (used the same way by element-component.ts and script-component.ts), which runs after the component is created so the setters reach the live component. The runtime setter path (changing the attribute after load) was already covered by the standard attributeChangedCallback → setter sync.

Update: the engine root cause is now fixed upstream in playcanvas/engine#8968 (merged), which adds these props to the system's _properties list. The initComponent() workaround here stays for the currently-supported engine range (^2.19.0 — 2.20.0 ships without the fix) and can be removed once the minimum engine version is bumped to a release that includes it. The code comment references #8968.

Testing

  • npm run lint and npm run build pass clean against playcanvas@2.20.0.
  • Verified in the example harness: a <pc-gsplat lod-range-min="1" lod-range-max="3"> reports component.lodRangeMin === 1 / component.lodRangeMax === 3 on the underlying engine component at load, the runtime setter path syncs correctly, and there are no console warnings/errors.

willeastcott and others added 5 commits June 25, 2026 22:47
Add lodRangeMin/lodRangeMax to the pc-gsplat element, completing the LOD
control surface alongside the existing lod-base-distance/lod-multiplier.
These clamp the LOD index selected by distance (min = finest allowed,
max = coarsest allowed); raising the min avoids downloading the largest,
highest-quality LOD files.

The engine's GSplatComponentSystem.initializeComponentData only applies a
fixed allow-list of properties and ignores lodRangeMin/lodRangeMax, so the
values are applied through the initComponent() hook after the component
exists rather than via getInitialComponentData().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
playcanvas/engine#8968 (merged) adds lodRangeMin/lodRangeMax to the gsplat
component system's _properties list, fixing the root cause at the engine
level. Note this in the comment so the initComponent() override can be
removed once web-components' minimum supported engine version includes the
fix. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
lodRangeMin/lodRangeMax were first added to GSplatComponent in engine
2.20.0, so versions earlier than 2.20.0 do not have them at all. The
gsplat system _properties allow-list omitted them only in 2.20.0; the
fix (playcanvas/engine#8968) shipped in 2.20.1. Reword the comment so it
no longer implies "2.20.0 and earlier" are affected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Engine 2.20.1 (playcanvas/engine#8968) adds lodRangeMin/lodRangeMax to
the gsplat component system's _properties allow-list, so they now apply
correctly via getInitialComponentData() like the other attributes. Move
them there and remove the initComponent() override.

Bump the playcanvas peer dependency to ^2.20.1 so consumers can't land
on 2.20.0, where these props exist on the component but are dropped from
initialization data.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@willeastcott willeastcott merged commit ce38491 into main Jun 29, 2026
2 checks passed
@willeastcott willeastcott deleted the expose-gsplat-lod-range-attributes branch June 29, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant