Skip to content

Render enchantment glint as a visible scrolling overlay - #87

Closed
HarnoorC wants to merge 13 commits into
NVIDIAGameWorks:mainfrom
HarnoorC:fix/tool-glint
Closed

HarnoorC wants to merge 13 commits into
NVIDIAGameWorks:mainfrom
HarnoorC:fix/tool-glint

Conversation

@HarnoorC

@HarnoorC HarnoorC commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #85. This head (f44d6f1) contains placement head ba90b9c and upstream a518eff through a normal merge. Review only the glint changes with git diff origin/fix/enchanted-tool-rendering origin/fix/tool-glint (comparison). The glint findings below are intentionally waiting for #85's review stage; this update only synchronizes the stack.

#85 fixes where enchanted items render in first person and leaves glint with main's cutout material, shell depth and layer identity. This PR makes the glint itself visible and animated.

Classify glint separately from cutouts and use the runtime's color-additive emissive blend. Separate retained layer identity from physical overlay depth: match surface stacks by geometry and pose, resolve substrates before glint, and place each glint beyond its own complete pattern stack. Compensate layer spacing and per-quad text and map spacing for the shared view-model scale (ViewModelSpace), and include that spacing in mesh identity.

Respect the layer's vertex format so glint ignores model dye and hurt overlays. Sample Glint Strength once per frame, apply it independently of model tint, and omit glint instances at zero. Calibrate the dark additive glint texture to intensity 500 so its purple band stays visible in daylight; ordinary emissive materials keep intensity 100. Custom additive layers on the block atlas borrow its albedo texture rather than copying the atlas.

Forward vanilla's item and entity glint texture transforms: bake the fixed 10-degree UV rotation and scale into each mesh, clear the unrelated item-atlas UV bounds, and scroll the shared glint texture at vanilla's phase and Glint Speed. The update descriptor and Java-to-JNI arrays are reused, so animation adds no per-frame Java allocation. This uses the published texture-update API without changing its native signature or the runtime pin.

Validation on f44d6f1:

  • gradlew.bat build: 817 plain JVM + 64 Fabric tests (881 total), no failures or skips.
  • Tooling is identical to Fix enchanted held-item placement and glint rendering #85, whose tools\\rtx.bat check --tests passed 1,163 tests and 178 subtests, one skipped.
  • Public-boundary checks: 24 tests + 18 subtests. Diff whitespace checks pass.
  • No independent glint implementation changes were made during this forward merge. The only conflict was combining test imports.
  • Existing visual evidence is from 86b5a7d, before the split, with the same glint implementation: stationary signed-in Prism captures over 240 frames showed a moving purple band and a readable gold texture. This integration head has not been rechecked in game. Scripted shutdown at that earlier head returned 0xC0000409; clean interactive shutdown remains unverified.

Open review findings on this change, to be resolved before it leaves draft:

  1. Layer identity is a counter per RenderLayer object. Vanilla builds a new layer on every getEnergySwirl and getBreezeWind call, so charged creepers, wither armour and breeze wind get a new retained instance every frame.
  2. Grouping surfaces by geometry places a glowing sign's outline and ink at the same depth, so most outline copies sit in front of the ink.
  3. A failed glint texture upload propagates to submitEntity and discards the whole owner, including the first-person hand.
  4. createMeshWithMaterial reads the text step and glint UV mode from the shared rigidMeshLookupKey.
  5. Intensity 500 applies to any GLINT_TRANSPARENCY layer, not only vanilla's glint textures.
  6. prepareSurfaceLayers dropped the null-texture guard and runs outside submitEntity's error handling. Its matching is quadratic in parts per entity.
  7. The regression tests compute expected depth from layer identity rather than through the production grouping.
  8. Not yet verified: first-person layer spacing when FOV changes, glint filtering and mipmaps, redundant GLINT checks after early returns.

Movement, denoiser and upscaler behaviour, extreme-FOV precision, patterned shields, and glint's night and cave lighting contribution still need visual review.

Signed-off-by: Harnoor Chima harnoorchima1@gmail.com

Apply view-model correction at the capture root so glint-wrapped vertices and rigid parts share camera-relative placement and scale. Keep held-light position calculations on the same corrected root.

Add regression coverage using Minecraft glint unions across camera angles, FOV scales, and hand positions.

Validation: gradlew.bat build test passed all 807 tests. In-game visual verification remains pending.
Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Forward pose-aware calls through vanilla Dual and Union consumers, including sprite-wrapped cuboids. Keep each consumer on its own pivot when base and glint layers interleave, so local meshes stay reusable and held-block lights retain their hand ownership.

Use the existing first-person pivot correction and reuse the model-view matrix, bone snapshot buffer, and held-light anchor vectors. Add headless Fabric integration coverage of real consumer dispatch, Minecraft camera conventions, capture finalization, mesh stability, card geometry, and light anchors.

Validation: gradlew.bat build test passed 800 plain JVM tests and 15 Fabric integration tests. Disabling only the union mixin made all seven camera-and-light regression cases fail; restoring it passed. Tooling checks passed 1,135 tests and 178 subtests, with one test skipped. In-game visual verification remains pending.
Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Apply first-person correction once to the common capture root so retained local poses and fully posed wrapper vertices agree. Preserve projected glint UVs emitted after normal(), and stream unposed geometry without filling the static mesh cache.

Rank glint shells after their bases and retain cuboid branches independently of discarded or overlay branches. Reuse the union-aware capture lookup for singleton iterators and reuse card-face scratch arrays. Remove obsolete pose accessors and wrapper comments.

Separate plain JVM and Fabric test tasks under check, and reject test classes in the reserved mixin package before discovery. Add projected-display glint, shell-order, mixed-cuboid, and iterator regression coverage.

Validation: root build/test passed 801 plain JVM tests and 25 Fabric integration tests. All five projected-glint cases failed with the prior per-bone correction restored; the shared-root fix passed. The reserved-package guard rejected a temporary misplaced class. Tooling checks passed 1,135 tests and 178 subtests, with one skip. In-game visual verification remains pending.
Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Give glint its own surface mode instead of treating the purple overlay as an opaque cutout. Use the runtime color-emissive blend and albedo emission, and keep glint coverage independent of substrate and instance alpha state.

Add material-state regressions and check the surface classification of real vanilla glint layers. Root build/test passed 804 plain JVM tests and 25 Fabric integration tests. Tooling checks passed 1,135 tests and 178 subtests with one skip. The supplied screenshot exposed the issue; visual verification of the corrected build remains pending.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Keep enchantment shell separation from shrinking with the first-person capture root. Store the resulting local depth in rigid mesh keys so held and world glint cannot share differently spaced geometry. Add capture regressions at the stationary pickaxe reproduction coordinates and a cache identity regression.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Classify transient geometry per part, keep mining cracks in a reusable local pose, and preserve layer ranks through pose snapshots and replay. Place glint above complete pattern stacks and keep first-person overlay spacing in a shared model space. Cache wrapper capture leaves and layer facts, route uncapturable sprite branches through vanilla cuboid rendering, and retire owned additive atlas materials correctly. Add production-path regressions and document the complete check task.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Keep static unposed parts reusable, isolate each surface stack, and honor glint tint and strength semantics. Scale text quad spacing with the view model, reuse managed atlas textures, and keep Fabric tests out of launcher and benchmark builds.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Apply the vanilla item and entity glint UV transforms, scroll their shared textures through the existing update API, and calibrate glint brightness for daylight. Reuse texture-update descriptors and JNI arrays so animation keeps stable meshes and avoids per-frame Java allocation.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Move the glint appearance work to its own branch so this change only
corrects where enchanted items render. Glint layers return to main's
cutout material, shell depth and layer identity, and the view-model
scale stays on RemixFirstPersonPass.

The shared capture-root correction, union and sprite look-through with
cached capture leaves, projected-glint transient parts, the block-local
crack pose, Vector3f held-light anchors and the separate Fabric test
task stay.

Validation: gradlew.bat check passed 801 plain JVM tests and 35 Fabric
integration tests.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Give glint its own surface mode with the runtime's color-additive
emissive blend instead of treating it as an opaque cutout. Place each
glint beyond its substrate and any banner pattern stack, keep retained
layer identity separate from that depth, and keep layer and text
spacing after the first-person view-model scale.

Glint layers carry no vertex colour, so ignore model dye and hurt
overlays on them. Honor Glint Strength and omit glint at zero. Apply
vanilla's item and entity glint UV transforms and scroll the shared
glint textures at vanilla's phase and Glint Speed through the existing
texture-update API, reusing the update descriptor and JNI arrays.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Keep upstream's Fabric loader version and renderer test task, the placement
branch's pre-discovery mixin-package guard, and independent test/check wiring.
Resolve the relocated BakedQuad test with upstream's file and sort the combined
mixin list. The launcher and both benchmark build descriptions exclude both
test suites.

Readers reviewed: fabricLoaderVersion is consumed by modImplementation and
fabricTestRuntime; fabricTest by check and its ordering against test;
verifyTestMixinPackage by fabricTest; the mixin list by Fabric Loader and
MixinPackageBoundaryTest.

Applicable AGENTS.md invariant:
"Ordinary classes must not live in the mixin package (MixinPackageBoundaryTest)."

Validation: full build, 803 plain and 46 Fabric tests; tooling gate, 1163 tests
and 178 subtests (one skipped). No placement, material, layer-identity, shell-
depth or pose-replay behavior was changed during conflict resolution.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Flush open projected vertices before acceptCuboid and replayCuboidPart close
their preceding run. The existing model-space expansion path already flushes;
test all three boundaries with real OverlayVertexConsumer UV generation.

Snapshot the reusable hand anchor as primitive coordinates in pending lights
and shadow constraints. A shared mutable position would alias the queued hands,
and Vec3d is immutable, so another cached vector cannot replace the allocation.
Keep collision arithmetic, sphere/disk fields, clearance and volumetric policy
unchanged. Extract the light-info builder so those readers are tested directly.

Move the tooling test above its main guard. The upstream merge also sorted the
mixin list. No glint material, layer identity, shell depth or pose replay changes.

Reader audit:
- acceptCuboid: RemixConsumerDispatch.renderCuboid; replayCuboidPart:
  RemixEntityPass.replayPose. Other boundaries: beginVertex, quad,
  acceptModelSpaceVertex and finishOpenVertex already flush; emitCuboidGeometry
  reaches acceptModelSpaceVertex from pooled meshes, beacon lenses and canvases.
- PendingAnalyticLight coordinates: createPendingSphereLight,
  createPendingHeldBeaconLight, updateLocalFirstPersonLights, submitEntityLight,
  buildEntityLightInfo and withoutVolumetricContribution.
- LightConstraint coordinates: chooseTargetOffset, clearanceRadianceScale and
  gapDeficit/selectContinuousCandidate. Compatibility constructors preserve the
  vector-input readers. Tests cover unchanged sphere, disk and shadow geometry.
- RemixAPI constructor: load and the counting test double. Protected access is
  the smallest seam for native-free production capture/submit tests; no native
  signature or runtime version changes. The fixture stands in only for texture
  loading and unchanged blend-extension marshalling.
- test_benchmark_build_skips_both_test_suites: pytest discovery/module entry.

Applicable AGENTS.md invariants:
"Avoid per-block/per-quad capture allocation and per-frame render allocation."
"A retained instance is submitted where it is created or mutated, never once per frame."
"Run entity capture on the render thread."

Validation: full build, 806 plain and 54 Fabric tests; tooling gate, 1163 tests
and 178 subtests (one skipped). Restoring missing flushes and lost union poses
fails four regressions; restored fixes pass the full build. Filtered plain
tests exclude Fabric, and launch builds exclude both test tasks. In-game
camera/compass/mining verification remains pending.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
Bring upstream main and placement head ba90b9c forward with a merge. Combine
both sides' regression-test imports; retain all tests and the existing glint
implementation. The glint findings remain for the stage after placement review.

The runtime reader audits and invariant checks are recorded in the inherited
placement commits cbad215 and ba90b9c. This integration adds no independent
runtime field or method changes.

Applicable AGENTS.md invariants:
"Ordinary classes must not live in the mixin package (MixinPackageBoundaryTest)."
"Run entity capture on the render thread."

Validation: full build, 817 plain and 64 Fabric tests (881 total). Tooling is
byte-for-byte identical to the placement branch, whose gate passed 1163 tests
and 178 subtests (one skipped). No rebasing or pushed-history rewriting.

Signed-off-by: Harnoor Chima <harnoorchima1@gmail.com>
@HarnoorC

HarnoorC commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

Folded back into #85. With placement fixed but main's glint unchanged, purple artifacts show around the held tool, so both halves have to land together. #85's branch now points at this PR's head f44d6f1; continue there.

I originally wanted to split the fix for enchanted tools into 2 PRs where the first PR would handle tool placement and the second one dealt with glint. However, there were purple artifacts on the tool even after fixing placement so I've decided to keep everything in one PR despite the code changes being very large.

@HarnoorC HarnoorC closed this Nov 3, 2026
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