Lulucat

Hogyan épített Kimi K3 digitális töltőtollvonást

Gaoge ZhangGaoge Zhang

A Lulucat Notesba a Freeform irányfüggő töltőtollát szerettük volna. A specifikáció egy kézírásról készült képernyőkép volt. Két modell, egy döntő kérdés és egy ellipszis alakú tollhegy után a víztoll úgy ír, ahogy kell. A kutatást, a kódot és a validációt Kimi K3 végezte a Fireworksnél.

Frissítve

Kézzel írt angol kurzív, rajta a „fountain pen” felirattal egy kínai kalligráfiasor fölött, ellipszis alakú tollhegyű töltőtollal rajzolva krémszínű papírra: a függőleges vonások vastagok, a vízszintesek vékonyak.

Az ebben a bejegyzésben bemutatott Lulucat Notes Metal-folyamattal renderelve.

A Lulucat Notesban van egy egyszerű toll és egy szövegkiemelő. Az ütemterv következő eszköze egy víztoll volt — a Freeformból és az Apple Notesból ismert irányfüggő töltőtoll, amelynél a függőleges vonások vastagon, a vízszintesek vékonyan jelennek meg. Az eszköz specifikációja nem dokumentum volt. Egy képernyőkép volt: három sor kézírás, a „pencilkit”, a „无边记” és a „这种有方向的水笔能力” szavak — ez az irányfüggő víztoll-képesség.

A korábbi Metal-folyamathoz hasonlóan ezt a munkát is Kimi K3 végezte, a Moonshot Fireworkson futó nyílt modellje: a mérést, a modellezést, a kódot és a validációt. Az ember átadta a képernyőképet, válaszolt egy kérdésre, és egy valódi iPaden ítélte meg a toll érzetét.

A specifikáció egy képernyőkép

Egy statikus kép nem tudja megmondani, miért vékony egy vonás. Csak azt mutatja meg, mennyire vékony, és hol. Ezért az első lépés a mérés volt. Soronként és oszloponként végigpásztáztuk a képernyőképet, minden vonás középvonalának elmozdulását követve meghatároztuk az irányát, majd a pásztázott szélességet a szög szinuszával valódi szélességgé alakítottuk:

VonásIrányValódi szélesség
Az „l” felszálló szára, „pencilkit”≈ 78°27.3 px
A „k” törzse, „pencilkit”≈ 90°28 px
A 力 balra lefelé tartó lendülete≈ 66°25.7 px
Kurzív összekötő vonások≈ 8°11 px
Kínai vízszintesek (横)≈ 0°6–11 px

A vastag és a vékony aránya ≈ 2.5. A illesztése a 66°-os pontra értéket ad — a függés az szerint csaknem lineáris, a csúcs pedig a függőleges tengelyen van. Lényegében egy dőlt tollhegy: vízszintes rés, amelyet a vízszintes írás soha nem nyit ki.

Első verzió: szélesség az irányból

Az első modell kézenfekvő volt. Minden bemeneti ponthoz kiszámította az irányt, az illesztett görbén keresztül szélességgé alakította, majd a rögzítés pillanatában belevéste az eredményt a pont sugarába. Az irányt oksági módon becsültük — az ív utolsó néhány pontjának exponenciálisan csökkenő súlyozott átlagaként, kettős szögterben számolva, hogy a haladási irány megfordulása ne oltsa ki a becslést. Csak a korábbi pontokat használjuk, így az élő és a véglegesített vonás bájtról bájtra megegyezik.

A builder megfelelt a saját egység-ellenőrzésén: a szintetikus vízszintes, függőleges, 45°-os és megfordított útvonalak az elméleti szélességeket sütötték be — 0.99, 2.52, 2.00 és 0.99 pontot. A rendereléshez egyáltalán nem kellett új kód: az előre beírt sugarú vonás csupán kerek lenyomatok lánca, és a point-sprite pipeline-unk már megrajzolta ezeket.

Az iPaden az embernek körülbelül tíz másodpercébe telt elutasítani: „ez művésztoll, nem víztoll”.

Egy kép, két lehetséges történet

Miért tűnt rossznak? Két lehetséges magyarázat volt, és a képernyőkép nem tudta szétválasztani őket:

  • Irányzár. A tollhegy geometriája vékony vízszinteseket és vastag függőlegeseket kényszerít ki, bármit is csináljon a kéz. Ezt valósította meg az első verzió.
  • Nyomás és sebesség. A toll nyomásvezérelt, a minta pedig csupán a kézírás dinamikája: a lefelé húzások természetesen erősebben nyomottak, az összekötők pedig természetesen gyorsak és könnyűek.

Mindkét magyarázat vékony vízszinteseket és vastag függőlegeseket eredményez a képernyőképen. A különbség akkor jelenik meg, amikor erősen rányomunk egy vízszintes vonásra. Az első verzió vékonyan hagyja. A nyomásérzékeny toll megvastagítja. Ezért feltettünk az embernek egy kérdést: vastagabbá kell válnia annak a vízszintes vonásnak, amelyre erősen rányomunk?

„Nem. A vízszintesek vékonyak maradnak.”

Az irányzár megerősítést nyert. De valami más is hibás volt, mert az első verzió szintén irányzáras volt.

A válasz a vonások végeiben volt

A következő nyom a felszálló szárak tetején volt. A mintában az „l” és a „k” törzsének kinagyítása két dolgot mutatott: egy egyenes vonás elejétől a végéig megtartja ugyanazt a szélességet, a vonásvégek pedig lapos, átlós vágások — egy vésőhegy alakja, amikor felemelkedik. Nem kerek pontok. Nem nyomás okozta elvékonyodások.

A minta két kézzel írt felszálló szárának közeli kivágata; mindkettő tetején lapos, átlós vágással végződik, és a szár teljes hosszában egyenletes a vastagsága.

Ezt jelentette valójában a „művésztoll érzése”. Az első verzió a minta kinézetét modellezte — a szélességet a becsült irány függvényeként —, de nem a tollat. Az iránybecslő egy szenzor: zajos bemeneten remeg, a sarkokban lemarad, és minden vonásvéget kör alakúra kerekít. Egy valódi tollhegynek egyik problémája sincs, mert nem számol semmit. A szélesség geometria.

Második verzió: ellipszis alakú tollhegy

A végső modellben egyáltalán nincs iránybecslő. A tollhegy egy tájolt ellipszis: a hosszú tengely vízszintes, a rövid tengely rögzített. Ennek az ellipszisnek a lenyomatait sűrűn helyezzük el a vonás útvonala mentén, és minden más a geometriából következik:

  • A vízszintes vonás a nyitott él mentén halad, ezért a szélessége mindig — állandóan vékony vonal, bármilyen nyomás mellett. Pontosan a megerősített specifikáció.

  • A függőleges vonás a teljes hosszú tengelyt keresztezi: , a vastag vég.

  • Az átlós vonás a haladási irányra merőlegesen veszi az ellipszis húrjának szélességét,

  • A vonásvégek ellipszisből vágott végek — a mintán látható, lapos tollhegy alakú végek, külön munka nélkül.

  • A nyomás csak a hosszú tengelyt skálázza, , így tintamennyiséget ad a lefelé húzásokhoz, és soha nem vastagíthatja meg a vízszintest.

A minta mérései alapján megtartottuk a pt és a pt értéket, vagyis ugyanazt a 2.5 arányt. A lenyomatok 0.5 pont távolságra vannak egymástól az ív mentén; 0.55 pontos rövid sugárral a legrosszabb esetű élhullámzás körülbelül egy pixel tizede.

A rendereléshez egy új fragment shader kellett, semmi más. A vertex format — pozíció, átmérő, szín — már mindent hordozott: az átmérő a hosszú tengely, a rövid tengely pedig egy meneten belüli uniform. A shader ugyanazzal a félpixeles fedettségi rámpával értékeli ki az ellipszis SDF-jét, mint a kerek lenyomataink, így pixelpontosan összehasonlítható a Core Graphics referenciaimplementációjával (fillEllipse lenyomatonként). A validáció a szokásos ellenőrzésen ment át: egy két töltőtollvonást tartalmazó szintetikus korpuszt mindkét módon rendereltünk, majd képpontról képpontra összevetettük — nulla szerkezeti eltérés, és egy véletlenszerűen ellenőrzött vízszintes vonás mindkét renderelőben 12 px-t mért.

Ugyanannak a kézzel írt „fountain” szónak két renderelése egymás mellett: balra irány szerint skálázott átmérőjű kerek lenyomatok láthatók lekerekített végekkel, jobbra ellipszislenyomatok lapos, tollhegy által vágott végekkel és egyenletesebb szélességgel.

Az első verzió balra, a második jobbra. Ugyanaz a kézírásos bemenet, ugyanaz a pipeline. A végek mindent elmondanak.

Az iPaden az új toll azonnal átment: „好,很好” — Jó. Nagyon jó.

A mellélövés megtartása

Az első verzió nem került a kukába. Érdekes ecset — egyszerűen nem víztoll. Ezért egy új kísérleti ecsetmenü első elemeként szállítottuk, azon a néven, amelyet az ember adott neki: 漏水的圆珠笔, a szivárgó golyóstoll. Az eszköztár kapott egy lombik alakú gombot, amely megnyitja a kísérletek szöveges listáját; a következő hozzáadása egyetlen sor a regisztrációban. Egy elutasított modell nem elvesztegetett munka, ha egyértelműen felcímkézett kísérletként kiadható.

Egy este iterációi

A teljes ív — mérés, modellezés, építés, eszközön való kipróbálás, kérdés, újramodellezés, újraépítés, validáció — egy estét vett igénybe. Kimi K3 a Fireworkson a ciklus teljes technikai oldalát vitte: kidolgozta a mérési pásztázásokat, a második találgatás helyett javasolta a döntő kérdést, a bizonyítékok megfordulásakor törölte a saját iránybecslőjét, és még az alkalmazás módosítása előtt kibővítette a pixel-diff tesztkörnyezetet. A Fireworks következtetési sebessége interaktívan tartotta a ciklust — a hosszú Metal- és Swift-diffek, a pixelanalizáló szkriptek és a korpuszeszközök elég gyorsan érkeztek ahhoz, hogy a megmaradó szűk keresztmetszet az emberi ítélet legyen.

Az együttműködés mintája ugyanaz volt, mint a Metal-folyamatról szóló bejegyzésben, és ismét bevált: a modell gyors és pontos; az emberé az ízlés és a teljes folyamatot lefedő ellenőrzés. Egyetlen, az érzetre vonatkozó visszajelzés — „művésztoll, nem víztoll” — elég volt ahhoz, hogy a modell megtalálja a pontos modellezési hibát, és egyszerűbb tervvel váltsa fel.

A helyes modell kisebbnek bizonyult a rossznál. A második verzió kevesebb mozgó alkatrésszel került ki, mint az első — nem volt benne becslő, simítási ablak vagy illesztett kitevő. A tollhegy nem számítja ki a szélességet. A tollhegy maga a szélesség.