Skip to content

insert: opt-in Traced mode for the Insert Hybrid shader - #604

Open
dcbenji wants to merge 1 commit into
freezy:masterfrom
dcbenji:feat/insert-traced-mode
Open

dcbenji wants to merge 1 commit into
freezy:masterfrom
dcbenji:feat/insert-traced-mode

Conversation

@dcbenji

@dcbenji dcbenji commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

AI-authored. Claude (Anthropic: Opus 5.5) wrote this code and the docs page at @dcbenji's request, and opened this PR on his behalf. A human has not reviewed it line by line. It was tested as described under Testing. It stays a draft until the automated review comes back clean.

What

An opt-in Traced mode for Pinball/Insert Hybrid, behind the material keyword _INSERT_TRACED. With it on, the body's glow comes from an offline path-traced render of the insert instead of the optical response map. The bulb image and the facet glints are still drawn live, through a facet map from the same render. An optional second render of the insert under the room, with the lamp off, replaces the live unlit body. With the keyword off the material is unchanged: both new custom-function nodes pass their inputs straight through.

  • InsertTraced.hlsl (new) and two custom-function nodes in the graph: one before InsertOptics (scales the live glow and bulb by the mix controls) and one after it (adds the traced light, glints and lamp-off layer). InsertOptics.hlsl is not touched.
  • 22 new material properties under a Traced Mode category. The keyword is multi_compile_local, fragment stage only, because player tables build their materials at runtime and a shader_feature would be stripped. That doubles the fragment variants of the Insert Hybrid: say if you'd rather have shader_feature plus a variant collection.
  • InsertTracedFields (editor): the controls and their tooltips in one place, so the HDRP and URP inspectors show the same sections with the same words (companion PRs below).
  • Look presets leave the Traced values alone (InsertMaterialPreset.IsStyle). They belong to the insert type and its bake (where the render sits, its elevations), not to a look shared between inserts. InsertPresetTests asserts it.
  • Docs: Inserts › Traced Mode (traced-mode.md, text only; no images committed).

The lamp-off brightness is a global, _InsertTracedOffEv (stops), which the table sets when it loads.

Why

The live optics fake the glow from the response map. A path-traced render of the actual plastic (faceted floor, starburst, skirt, a bulb in the pocket) gives the depth and the bright facet edges a real insert has. The glints and the bulb's parallax stay live because a render can't know where the eye is. @dcbenji tuned it by eye on T2's rectangles, circles and triangles, lit and unlit, and prefers it to the live look on those inserts.

Not in this PR

  • Making the maps. The renders were made by hand (LuxCore, four elevations, 1k spp + OIDN, one insert per scene). The insert baker only bakes the live mode's maps. If you want the mode, the next step is a Traced option in the baker: a Blender script next to bake_insert.py, Cycles by default and LuxCore when installed.
  • Room brightness. The lamp-off layer should dim and brighten with the room (the HDRI/sky) and not with the lamps. Do you already plan a room or environment brightness setting for the player? If so, _InsertTracedOffEv would follow it (room stops plus a per-table offset). We have a sketch (a per-table setting next to Insert Brightness) if that helps, as a separate PR.

Testing

  • On upstream master with the two companion branches (Unity 6000.5.0f1, Linux/Vulkan): T2 (HDRP) and an Attack from Mars URP project both compile with no script or shader errors, and the Traced sections draw in both inspectors.
  • Look-dev on T2: 41 inserts in three bake types (rect l43-48/l53-58, round l61-65/l71-75, triangles); the per-type values were tuned by eye on a slider bench.
  • EditMode tests in the T2 project: 1985 of 1985 pass, including InsertPresetTests with its new Traced assertions.
  • URP's BuildInsertShader, called directly: the toggle's value restores the keyword (on and off). HDRP's resolver does the same thing but wasn't exercised.
  • Not tested: a full .vpe round trip into the Player. The translator ships the Traced maps as linear, uncompressed data, but HDR (EXR) source maps through the texture cook are unverified.

Companion PRs: VisualPinball/VisualPinball.Unity.Hdrp#37 (inspector section, .vpe keyword restore, linear Traced maps) and VisualPinball/VisualPinball.Unity.Urp#33 (inspector foldout, keyword restore). Both need this one.

🤖 Generated with Claude Code

@greptile-apps

greptile-apps Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with a non-blocking filtering issue remaining for small inserts.

Findings

  1. P2 Small inserts can shimmer ▶

Summary

Adds an opt-in Traced mode to Pinball/Insert Hybrid.

  • Insert Hybrid can light the body from a traced render and keep its highlights view-aware.
  • Insert looks keep each insert's traced bake settings.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Material inputs] --> B[InsertTracedPre]
    B --> C[InsertOptics]
    C --> D[InsertTraced]
    M[Traced maps] --> D
    D --> E[Body color, normal and light]
Loading

Reviews (2) · Last reviewed commit: "insert: add an opt-in Traced mode to the..." · Reviewed by Greptile

Comment thread VisualPinball.Unity/Assets/Shaders/Srp/Insert/InsertTraced.hlsl Outdated
float3 vbInside = refract(-vb, float3(0.0, 1.0, 0.0), rcp(eta));
float2 slide = (vbInside.xz / max(-vbInside.y, 0.25) - tracedInside.xz / max(-tracedInside.y, 0.25))
* (_TracedGeometry.z * 0.001 / max(_TracedFrame.w, 1e-4));
float light = dot(SAMPLE_TEXTURE2D_LOD(_TracedLight, sampler_TracedLight, InsertTracedUv(card) + slide, 0), weights);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Small inserts can shimmer

The baked light and room maps always read mip level zero. When an insert is small on screen, this skips the averaged texture levels and can make fine baked edges shimmer as the camera moves.

Use screen-size-aware filtering for _TracedLight and filtering that keeps the four _TracedEnv tiles separate. Document that both maps need mipmaps.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 65ed17a. _TracedLight is sampled with the gradients of its UV (SAMPLE_TEXTURE2D_GRAD). _TracedEnv picks its mip level from the UV derivatives in slice texels, capped at 4, and keeps half a texel of that level in from each slice edge. A slice is a 512 power-of-two block, so its mip texels never span two slices. The docs page now says to import all three maps with mipmaps. The test bakes have none yet, so on them this is a no-op until they're re-imported.

With the _INSERT_TRACED keyword on, the body glow comes from an offline
path-traced render of the insert (four view elevations, one per channel)
instead of the optical response map. The bulb image and the facet glints
are drawn live through a facet map from the same render, and an optional
lamp-off render of the insert under the room replaces the live unlit body.
With the keyword off, the material is unchanged.

The controls and their tooltips live once in InsertTracedFields, for both
pipelines' inspectors. The lamp-off brightness is the global
_InsertTracedOffEv (stops), set by the table when it loads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dcbenji
dcbenji force-pushed the feat/insert-traced-mode branch from fe6ec31 to 65ed17a Compare October 22, 2026 03:13
@dcbenji
dcbenji marked this pull request as ready for review October 22, 2026 03:16

This branch has not been deployed

No deployments
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