port: draw the measured additive blend -- main_menu 13.21 -> 10.67

The Decoder logged RB_BLENDCONTROL0 per draw in Canary on both screens.
0x01010101 is src=ONE dst=ONE, additive. That makes the blend a transcription
rather than my proposal, and they withdrew the "any blend you choose is authored"
instruction explicitly.

Their control is what licenses the change: one pixel shader, 0xE59B2B3DA4AA9008,
runs with BOTH blend states on the main menu -- 12 additive draws and 18
alpha-over. The frames and ptbase share a shader; only the blend register differs.

authored/rendering.json gains additive_elements per screen. Every id is a measured
draw and the reach is written beside it.

verify-capture: main_menu 13.21 -> 10.67 (0.06 % -> 0.02 %), extras 13.38 ->
11.43, main menu with ptbtn04 focused 13.82 -> 11.36. Per element, ptframe1
22.72 -> 4.17 and ptframe2 13.09 -> 3.32.

Neutrality control, free with the table: publisher_logo 2.17 and developer_logos
3.05 are unchanged to the digit. Those are the screens whose metric is absolute
and they carry no additive element, so the rewrite that routed every draw through
RenderingServer canvas items did not change the picture. The improvement is the
blend, not the plumbing.

RenderingServer rather than child Node2Ds because boot.gd calls view.queue_redraw()
from nine places and none reaches a child node -- bands would paint the previous
pose, which under --script=wait is a plausible wrong capture rather than an error.
Runs are recomputed per frame: the additive elements are consecutive on both
measured screens, and that is an accident of those two screens.

And the change first ran with the material left at its default MIX, moving
ptframe1 from 22.72 to 22.69. Nothing errored and a 0.03 move is a plausible
negative result. It was caught only because the measurement predicted a large move.

Not done: ptframe4 is now the worst element on EXTRAS at 16.19x the frame mean and
additive would plainly help it. It is not in the measured table, so it is not in
the file. Filed in BLOCKED.md with pteff21/22/23, which are also in no captured
draw.

Refuted, mine: "neither frame has a fully-opaque pixel" was true and was not the
discriminator -- pteff10 has max alpha 130, no opaque pixel, and measures nearly
exact. The direction survived; the reason for it did not.
This commit is contained in:
Sylpheed port agent
2026-08-31 06:18:11 +00:00
parent 0a054d681b
commit c453d8dade
5 changed files with 277 additions and 12 deletions

View File

@@ -285,6 +285,7 @@ func _ready() -> void:
var rendering: Variant = export_tree.authored("rendering.json")
_draw_leaf_for = [] if rendering == null else rendering.get("draw_leaf_for", [])
_loop_leaf_screens = [] if rendering == null else rendering.get("loop_leaf_on_screens", [])
_additive_elements = {} if rendering == null else rendering.get("additive_elements", {})
# `--no-hold` plays a screen's groups PAST their rest instead of clamping each
# element at its own `rest.t`. A diagnostic, not a mode: `rest.t` is the last
# HOLD keyframe before the exit, not the settled state, and the only way to
@@ -312,6 +313,7 @@ func _ready() -> void:
view.looping_focus = _looping_for(name)
view.loop_phase_units = _loop_phase
view.draw_leaf_for = _draw_leaf_for
view.additive_elements = _additive_elements
view.loop_leaf = _loop_leaf_screens.has(name)
view.focused_id = _force_focus
if not view.load_screen(export_tree, name):
@@ -406,6 +408,8 @@ var _pending: Variant = null
var _looping: Dictionary = {}
## `authored/rendering.json` `draw_leaf_for`.
var _draw_leaf_for: Array = []
## `authored/rendering.json` `additive_elements` -- measured off the running game.
var _additive_elements: Dictionary = {}
## `authored/rendering.json` `loop_leaf_on_screens`.
var _loop_leaf_screens: Array = []
var _script: PackedStringArray = PackedStringArray()
@@ -558,6 +562,7 @@ func _advance() -> void:
view.looping_focus = _looping_for(name)
view.loop_phase_units = _loop_phase
view.draw_leaf_for = _draw_leaf_for
view.additive_elements = _additive_elements
view.loop_leaf = _loop_leaf_screens.has(name)
if not view.load_screen(view.tree, name):
push_error(view.tree.error)
@@ -917,6 +922,7 @@ func _menu_arrive() -> void:
view.looping_focus = _looping_for(name)
view.loop_phase_units = _loop_phase
view.draw_leaf_for = _draw_leaf_for
view.additive_elements = _additive_elements
view.loop_leaf = _loop_leaf_screens.has(name)
if not view.load_screen(view.tree, name):
push_error(view.tree.error)