MilkDrop fidelity: stage rule, fixed composite and defaults - #611
Merged
Merged
Conversation
MilkDrop reads the main wave's alpha from the file as `fWaveAlpha` (state.cpp:1383). `wave_a` is the name per-frame code uses, and a header line with it is never read. The five builtin presets and the generator wrote `wave_a`, so in MilkDrop they drew the wave at its default 0.8. All 10,347 corpus files write fWaveAlpha and none writes wave_a in the header. The engine reads both names, so nothing changes on screen here: for the builtins and 199 generated presets the engine's wave_a is the same with either key. The generator's golden hashes change with the text; its version stays 1 because the same code still gives the same picture. Refs #580, #560
Checked against Nullsoft's code (jecassis/foo_vis_milk2 5b44cea) and, for the fixed pipeline's blend passes, the D3D9 code it was ported from (BeatDrop 53d83ee). Stages by version. MilkDrop picks the warp and composite shaders by the file's version, not by whether shader text exists. A file with no MILKDROP_PRESET_VERSION, or one below 200, is a MilkDrop 1 preset. 200 uses PSVERSION; 201 and above use PSVERSION_WARP and PSVERSION_COMP, each 2 when missing (state.cpp:1328-1348). A stage with a version and no text gets a shader written at load time with the file's values baked in (plugin.cpp GenWarpPShaderText, GenCompPShaderText). With fidelity on the engine follows this, and switching fidelity rebuilds the running preset's stages. Fixed composite. MilkDrop draws the flags with blend passes of a white quad: brighten is 1-(1-c)^2 and solarize 2c(1-c). The engine used sqrt(c) and 4c(1-c), the formulas of the shader MilkDrop generates. Echo orientation is (int)x % 4 with C's sign rule. Gamma is drawn as additive redraws, so below 1 it is not applied while echo is on. When two presets whose echoes point different ways blend, the echo fades out before the snap point and back in after it. Defaults. Keys a file does not write take MilkDrop's defaults: decay 0.98, gamma 2.0, echo zoom 2.0, wave alpha 0.8, mv_l 0.9, grid 12x9, border sizes 0.01 and inner border colour 0.25. The per-frame reset wrote the pool's 0 back every frame. Init code sees the defaults too, and a centre of 0 stays in the corner. Measured. Every flag, gamma and orientation case rendered through the engine reads back within 2/255 of MilkDrop's formula, with fidelity on and off (66 of 66). The 900-preset sample sorts into the same classes before and after. Of 120 brighten presets 99 changed (median 3.8%); of 83 solarize presets 63 changed, and median brightness went from 0.291 to 0.112. 14 new tests, 5 updated; the docs' test count follows. Refs #580, #560
A preset gives a mash-up its warp or composite part only if MilkDrop would draw that shader: besides a non-empty shader line, the stage's version under MilkDrop's rule must be above 0. A MilkDrop 1 file, or one whose PSVERSION_WARP is 0, no longer gives a part that neither MilkDrop nor the engine draws. The version written for a donated shader is the one its preset has for that stage, by the same rule as the engine's md2Versions. A version value that is not wholly a number counts as missing, as in the parser, and takes the rule's default. The part test is now checked against the engine's stage choice rather than against the presence of shader text, with eight version edge cases added; composing with a warp from a PSVERSION_WARP=0 preset writes version 0 and the engine draws the fixed warp. Refs #579, #580, #560
The stage rule, the fixed composite, MilkDrop's defaults and the fWaveAlpha key, with the measurements, in the README feature list and a ROADMAP entry under #580. The entry also records what was found while finishing this and comes next: preset shaders get the full hue colour in MilkDrop whatever fShader says, and a few keys fall back to other values when a file leaves them out. Refs #580
The mash-up id carries the rule version so that a rule change which alters the text of the same recipe never overwrites an earlier save. Following MilkDrop's stage rule is such a change: a warp from a preset with PSVERSION_WARP=0 used to be written as version 2, and the engine drew it; it is now written as 0. A recipe from the history saved again now writes md_mix2_... next to the old md_mix1_... file instead of replacing it. Nothing recognises mash-ups by the prefix, so older saves stay ordinary presets. Refs #579, #580
The README now says most values a preset leaves out take MilkDrop's defaults, not all of them: the five wave keys MilkDrop reads as 0 when missing, wave smoothing, the volume fade range and shape colours come in the next change. The ROADMAP records the mash-up rule version, the part test's stage condition, and that a partial fShader lands twice in a generated composite stage until the hue fix (the one corpus preset with such a stage has fShader at 0). Refs #580, #579
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-ups from the MilkDrop fidelity audit, checked against Nullsoft's code (jecassis/foo_vis_milk2 5b44cea) and, for the fixed pipeline's blend passes, the D3D9 code it was ported from (BeatDrop 53d83ee). Everything is behind the fidelity switch; with it off the legacy paths are unchanged.
MILKDROP_PRESET_VERSION, or one below 200, means a MilkDrop 1 preset, and its shader text is ignored.PSVERSION; 201 and above usePSVERSION_WARPandPSVERSION_COMP, each 2 when missing.1−(1−c)²and solarize is2c(1−c); the engine usedsqrt(c)and4c(1−c), the formulas of the generated shader. Echo orientation is(int)x % 4. Gamma below 1 is not applied while echo is on. When two presets whose echoes point different ways blend, the echo fades out and back in instead of flipping.mv_l0.9, grid 12×9, border sizes 0.01, inner border colour 0.25. Init code sees them too, and a centre of 0 stays in the corner.fWaveAlpha, the key MilkDrop reads. The builtins and the generator wrotewave_a, so MilkDrop drew their wave at its default 0.8. Nothing changes on screen in our engine; the generator's golden hashes were renewed and its version kept.Measured
main:echo_orientper frame.Found here, fixed in the next PR
Hue colour in preset shaders. MilkDrop gives every composite shader the full hue colour ("since we don't know if shader uses it or not").
fShaderscales it only on the fixed path and in the generated shader. Thehue_shaderchange in 52c7391 (MilkDrop Phase 2: visual rendering quality, user textures (img.ini), motion vectors, and smooth preset transitions #560) appliedfShaderto preset shaders too. With fidelity on, 914 corpus presets lost the colour and 36 got part of it.Keys that fall back to other values when missing:
wave_r,wave_g,wave_b,wave_xandwave_y: MilkDrop reads them asrot's value, which is 0.No corpus preset and none of ours leaves them out.
Tests
npm test: 2181 of 2181 pass, and each commit passes on its own. The changed files also pass under Linux emulation.npm run smoke: PASS, with the userData checksums unchanged.Refs #580
Refs #579
Refs #560