Skip to content

fix(gsplat): apply lodRangeMin/lodRangeMax from component init data#8968

Merged
willeastcott merged 2 commits into
mainfrom
fix/gsplat-lodrange-init-clone
Jun 26, 2026
Merged

fix(gsplat): apply lodRangeMin/lodRangeMax from component init data#8968
willeastcott merged 2 commits into
mainfrom
fix/gsplat-lodrange-init-clone

Conversation

@willeastcott

Copy link
Copy Markdown
Contributor

Description

lodRangeMin and lodRangeMax were added to GSplatComponent in #8908, but were never added to the gsplat component system's _properties list. As a result they were:

  • silently ignored when passed as initialization data to addComponent('gsplat', { lodRangeMin, lodRangeMax }), and
  • dropped on clonecloneComponent copies state via the same _properties list, so duplicating/templating/entity.clone()-ing a gsplat entity reset both properties back to their defaults (0 / 99).

This adds them to _properties, next to the sibling lodBaseDistance / lodMultiplier props that were already there. The component setters already exist and propagate to the GSplatPlacement, so no other engine change is needed.

Also included

  • Test: new test/framework/components/gsplat/component.test.mjs covering defaults, init-from-data, setter clamps, and clone preservation (there was no gsplat component test before). I confirmed the init/clone cases fail without the _properties change.
  • Examples: splat-portal and world now pass their static LOD values directly to addComponent rather than assigning them immediately afterwards. This is behavior-preserving — init data is applied before asset, so _onGSplatAssetLoad copies the identical values onto the placement. The other gsplat LOD examples (lod-streaming, lod-streaming-sh, relighting, vr-lod, downtown, depth-of-field, billions) set these dynamically via preset/toggle handlers or from the loaded asset's LOD count, so they're intentionally left as-is.

Checklist

  • I have read the contributing guidelines
  • My code follows the project's coding standards
  • This PR focuses on a single change

lodRangeMin and lodRangeMax were added to GSplatComponent in #8908 but
never added to the component system's _properties list. As a result they
were silently ignored when passed to addComponent() and dropped when a
gsplat component was cloned (reset to their defaults of 0 / 99). Add them
alongside the sibling lodBaseDistance/lodMultiplier properties.

Also adds a GSplatComponent test covering init-from-data and clone, and
simplifies the splat-portal and world examples to pass their static LOD
values directly to addComponent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2261.0 KB (+0.0 KB, +0.00%) 581.6 KB (+0.0 KB, +0.00%) 452.6 KB (+0.2 KB, +0.05%)
playcanvas.min.mjs 2258.4 KB (+0.0 KB, +0.00%) 580.7 KB (+0.0 KB, +0.00%) 451.5 KB (−0.4 KB, −0.08%)

@willeastcott willeastcott requested a review from mvaligursky June 25, 2026 22:13
@willeastcott willeastcott self-assigned this Jun 25, 2026
@willeastcott willeastcott added the area: graphics Graphics related issue label Jun 25, 2026
@willeastcott willeastcott merged commit a54aaa4 into main Jun 26, 2026
10 checks passed
@willeastcott willeastcott deleted the fix/gsplat-lodrange-init-clone branch June 26, 2026 08:37
willeastcott added a commit that referenced this pull request Jun 26, 2026
…8968)

lodRangeMin and lodRangeMax were added to GSplatComponent in #8908 but
never added to the component system's _properties list. As a result they
were silently ignored when passed to addComponent() and dropped when a
gsplat component was cloned (reset to their defaults of 0 / 99). Add them
alongside the sibling lodBaseDistance/lodMultiplier properties.

Also adds a GSplatComponent test covering init-from-data and clone, and
simplifies the splat-portal and world examples to pass their static LOD
values directly to addComponent.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
willeastcott added a commit to playcanvas/web-components that referenced this pull request Jun 26, 2026
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>
willeastcott added a commit to playcanvas/web-components that referenced this pull request Jun 29, 2026
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>
willeastcott added a commit to playcanvas/web-components that referenced this pull request Jun 29, 2026
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 added a commit to playcanvas/web-components that referenced this pull request Jun 29, 2026
* Expose lod-range-min and lod-range-max attributes on pc-gsplat

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>

* Reference upstream engine fix in initComponent workaround comment

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>

* Correct initComponent comment: only engine 2.20.0 is affected

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>

* Drop initComponent workaround for lodRangeMin/lodRangeMax

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>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants