Files
Sylpheed/docs/re/splash-glow-is-a-baked-texture.md
sylph-decoder e263041337 re: the splash blur is a TEXTURE -- palogo_*_eff is a baked 10-px glow
Play-test finding 4, answered as a mechanism and from the disc, so it
generalises instead of describing one boot.

ui-splash-draw-pass.md excluded a post-process from GPU state and closed
with "that softness is in the texture or in which quads are drawn, not in
a pass", leaving the two unseparated. It is both, and they are one fact:
each logo ships a second texture that IS the blur -- the same artwork
outset by exactly 10 px per side, concentric to <=1.5 px, drawn as its
own alpha-over quad.

Three results, each with its control:

* The capture's eight anonymous quads are NAMED from the disc. Predicting
  each NDC rect from declared position + decoded sprite size matches all
  eight bijectively; every match <=0.0061, every runner-up >=0.0272, a
  4.5-8.9x margin. That margin is the control -- eight similar boxes
  would match anything.

* REFUTES splash-quad-timeline.txt's "the same three rects scaled
  slightly larger" (my own earlier wording). The x and y scale factors
  differ by up to 0.28; a uniform scale cannot do that, a fixed 10-px
  border can. The conclusion it supported (draw all six quads) stands;
  the model was wrong, and the wrong model tells a port to scale a
  sprite.

* The T8aD blend bit tested OUT of sample on entries 10/11, which were
  not in its 35-row fit and are the screens under complaint.
  Pre-registered additive=false for all eight against 0 additive draws in
  1048; held 8/8, with the control still reporting 9 additive on entry 6.

Also resolves a REFUTED.md 🟡 <our-reader> in the reader's favour: the
prediction is ours and the target is the oracle, so the agreement is
evidence about the reader rather than a claim resting on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
2026-09-01 18:24:14 +00:00

164 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The splash "blur" is a baked glow texture — `palogo_*_eff.t32`, a 10-pixel concentric outset
**Status: ✅ decoded (disc), confirmed against the oracle 8/8.** 2026-09-01.
Instruments: prediction ⟨disc⟩ (`parse_build` + `t8ad::parse` over
`GP_TITLE.pak`); target ⟨capture⟩ (the guest vertex stream in
[`data/splash-quad-timeline.txt`](data/splash-quad-timeline.txt) and
[`data/splash-draw-pass-census.txt`](data/splash-draw-pass-census.txt)).
Answers play-test finding 4 — *"the splash fade/blur is more pronounced in the
game"* — at the level the human asked for: **the mechanism, not a curve.**
---
## The answer in one line
> **There is no blur pass and no blur filter. Each logo ships a second texture
> that IS the blur — `palogo_<x>_eff.t32`, the same artwork outset by exactly
> 10 pixels on every side — and the game draws it as an extra alpha-over quad
> concentric with the logo. Drawing the logo alone loses the glow entirely.**
[`ui-splash-draw-pass.md`](ui-splash-draw-pass.md) had already excluded a
post-process from GPU state and closed with *"that softness is in the **texture**
or in **which quads are drawn**, not in a pass"*, leaving the two unseparated.
It is **both, and they are the same fact**: a dedicated soft-edged texture, drawn
as its own quad.
## 1 — the capture's eight anonymous quads, named from the disc
A draw capture sees geometry, not names. `splash-quad-timeline.txt` could only
call them `Q0…Q7`. Predicting each rect from the **declared position** and the
**decoded sprite size**`x_ndc = 2x/1280 1`, `y_ndc = 1 2y/720` — names all
eight, bijectively:
| sprite (disc) | quad | max abs edge error | runner-up | draws |
|---|---|---|---|---|
| `palogo_sqex.t32` | Q0 | 0.0056 | 0.0367 | 111 |
| `palogo_sqex_eff.t32` | Q7 | 0.0061 | 0.0339 | 8 |
| `palogo_gamearts.t32` | Q1 | 0.0056 | 0.0272 | 87 |
| `palogo_gamearts_eff.t32` | Q4 | 0.0037 | 0.0306 | 21 |
| `palogo_seta.t32` | Q2 | 0.0050 | 0.0278 | 87 |
| `palogo_seta_eff.t32` | Q5 | 0.0037 | 0.0328 | 21 |
| `palogo_anima.t32` | Q3 | 0.0050 | 0.0272 | 87 |
| `palogo_anima_eff.t32` | Q6 | 0.0056 | 0.0356 | 21 |
**8 named, 0 unmatched.** The capture quantises to 0.01 NDC, so the tolerance is
0.010; every match lands at ≤ 0.0061 and every **runner-up** sits at ≥ 0.0272 —
a 4.5× to 8.9× margin. **That margin is the control**: eight similar boxes would
match anything, and these do not.
Reproduce: `cargo run --release -p sylpheed-formats --example splash_quad_names`.
📌 **This also settles a `⟨our-reader⟩` 🟡 in the right direction.** The
prediction comes from our reader; the target is the oracle's vertex buffer. The
agreement is therefore **evidence about the reader**, not a claim resting on it —
`parse_build`'s declared placement and `t8ad`'s decoded dimensions reproduce
what the GPU actually drew, on both splash bundles, to within 4 screen pixels.
A disagreement would have indicted the reader instead.
## 2 — what an `_eff` companion actually is
`splash-quad-timeline.txt` described the companions as *"the same three rects
**scaled slightly larger**"*. That is an inference from four rounded NDC numbers,
and the disc refutes it:
```
palogo_sqex_eff outset 10x10 px, centre off by ( 0.0,-0.5), scale 1.030/1.309 NOT uniform
palogo_gamearts_eff outset 10x10 px, centre off by (-0.5, 0.0), scale 1.042/1.282 NOT uniform
palogo_seta_eff outset 10x10 px, centre off by ( 0.5,-0.5), scale 1.087/1.236 NOT uniform
palogo_anima_eff outset 10x10 px, centre off by (-1.5, 1.0), scale 1.049/1.147 NOT uniform
```
| | logo | `_eff` | Δ |
|---|---|---|---|
| `sqex` | 666×68 @ (309,330) | 686×89 @ (299,319) | **+20×+21 px, 10,11** |
| `gamearts` | 500×71 @ (390,164) | 521×91 @ (379,154) | **+21×+20 px, 11,10** |
| `seta` | 240×89 @ (521,316) | 261×110 @ (511,305) | **+21×+21 px, 10,11** |
| `anima` | 388×136 @ (446,449) | 407×156 @ (435,440) | **+19×+20 px, 11,9** |
* **Concentric** — the two centres agree to ≤ 1.5 px in every pair.
* **A constant 10-px outset per side**, in *both* axes, on all four pairs.
* **Not a scale.** The x and y scale factors differ by 0.06 to 0.28. A
"slightly larger copy" model predicts they match; they do not, and the
narrower the logo's height the further apart they get — exactly what a
*fixed-width* border does and a scale cannot.
A fixed 10-pixel halo around the same artwork, in a separate texture, is a
**pre-rendered blur**. Nothing computes it at runtime; it was computed by the
artist and shipped.
Asserted by `eff_is_a_concentric_outset_not_a_scale` in the same example, which
fails if the pair is not concentric, if the outset is not uniform, if it leaves
8…12 px, **or if the scale factors turn out uniform after all** — that last
assertion is the one that would reinstate the reading it displaces.
## 3 — the blend, tested out of sample on these exact screens
[`structures/ui-blend-mode-decoded.md`](structures/ui-blend-mode-decoded.md)
established `T8aD +0x04` bit `0x02` on **35 elements over three screens**
(`GP_TITLE` entries 2, 4, 5, 6). Entries **10 and 11 were not in that sample**,
and they are the screens the play-test says are wrong.
**Pre-registered before reading the disc:** the census finds `0x01010101`
(additive) in **0 of 1 048** splash draws, so if the bit generalises, all eight
splash sprites must read `additive = false`.
```
palogo_sqex.t32 / _eff, palogo_{gamearts,seta,anima}.t32 / _eff
word04 = 0x00008830 -> alpha-over (8 of 8)
additive=0 alpha-over=8 no-header=0
control -- entry 6 through the SAME code path reports additive=9: PASS
```
**Prediction held.** The control matters: the same accessor reports 9 additive
sprites on entry 6, so `additive=0` is a fact about the splashes and not a
harness stuck on one answer.
`cargo run --release -p sylpheed-formats --example splash_blend_check`.
🔴 **So the glow is NOT additive.** It is composited source-over like everything
else, and its softness comes entirely from the texture's own alpha. A port that
"adds a glow" by switching these quads to additive blending will be wrong in a
new way.
## What this means for the port
1. **Draw `palogo_sqex_eff.t32`, `palogo_gamearts_eff.t32`, `palogo_seta_eff.t32`
and `palogo_anima_eff.t32` as their own quads**, at their own declared
positions, with their own keyframe alphas. They are not decorations of the
logo element and they are not derivable from it.
2. **Do not scale the logo to produce them.** They are separate art. A scaled
logo has a border that grows with the logo; the real one is 10 px regardless.
3. **Source-over, not additive**, on all eight.
4. **They are short-lived.** Declared `0@0 → 255@15 → (255 or 212)@30 → 0@45`
against the logo's `0@15 → 255@30 → … → 0@210` (developer) / `0@255`
(publisher). The halo flashes during the entry and is gone for the whole hold.
That is the "more pronounced" moment and it is ~45 units long.
## Refutation attempt, recorded per the adversarial duty
**Target:** `ui-blend-mode-decoded.md`'s *"`T8aD +0x04` bit `0x02` set ⇒
additive"*, tested where it was never fitted — the two splash bundles, on the
screens under play-test complaint, against 1 048 captured draws.
**Result: it SURVIVED, out of sample, 8/8, with a passing control.**
**Second target, same iteration:** `splash-quad-timeline.txt`'s *"the same three
rects scaled slightly larger"*. **REFUTED** — §2. The companions are concentric
10-px outsets, and their x and y scale factors differ by up to 0.28, which a
uniform scale cannot produce. The conclusion the phrase supported (there are six
quads and an export must draw all six) is unaffected; the *model* of what the
extra three are was wrong, and the wrong model tells a port to scale a sprite.
## Reach
⟨disc⟩ for §2 and §3, so both generalise to every screen that uses the same
structures — the `_eff` naming convention and the blend bit are properties of the
shipped data, not of a boot. §1's *agreement* is ⟨disc⟩ × ⟨capture⟩ over the two
splash bundles specifically.
**Not settled here:** whether the `_eff` alpha ramp the port should use is the
declared one or the captured one (they differ; see
[`ui-keyframe-time-unit.md`](ui-keyframe-time-unit.md)), and the plate-late
finding (play-test 3), which is untouched.