Lulucat

Kimi K3 એ ડિજિટલ ફાઉન્ટેન પેન સ્ટ્રોક કેવી રીતે બનાવ્યો

Gaoge ZhangGaoge Zhang

અમને Lulucat Notesમાં Freeformની દિશા-આધારિત ફાઉન્ટેન પેન જોઈએ હતી. સ્પેસિફિકેશન હસ્તલિખિત લખાણનો એક સ્ક્રીનશૉટ હતો. બે મોડેલ, એક ભેદ પાડતો પ્રશ્ન અને એક એલિપ્સ નિબ પછી વોટર પેન જે રીતે લખવી જોઈએ એ રીતે લખે છે. Fireworks પર સંશોધન, કોડ અને ચકાસણી Kimi K3એ કરી.

અપડેટ કરેલું

ક્રીમ રંગના કાગળ પર એલિપ્સ-નિબ ફાઉન્ટેન પેનથી દોરાયેલી હસ્તલિખિત અંગ્રેજી કર્સિવ, જેમાં “fountain pen” લખેલું છે અને તેની નીચે ચીની કૅલિગ્રાફીની એક રેખા છે: ઊભા સ્ટ્રોક જાડા અને આડા સ્ટ્રોક પાતળા.

આ લેખમાં વર્ણવાયેલી Lulucat Notesની Metal પાઇપલાઇનથી રેન્ડર થયેલું.

Lulucat Notesમાં સાદી પેન અને હાઇલાઇટર છે. રોડમૅપનું આગલું સાધન વોટર પેન હતું — Apple Notes અને Freeformમાં ઓળખાતી દિશા-આધારિત ફાઉન્ટેન પેન, જેમાં ઊભા સ્ટ્રોક જાડા અને આડા સ્ટ્રોક પાતળા દેખાય છે. આ સાધનની સ્પેસિફિકેશન કોઈ દસ્તાવેજ નહોતી. તે હસ્તલિખિત લખાણની ત્રણ પંક્તિઓ ધરાવતો સ્ક્રીનશૉટ હતો: શબ્દો “pencilkit”, “无边记” અને “这种有方向的水笔能力” — આ દિશા-આધારિત વોટર-પેન ક્ષમતા.

અગાઉની Metal પાઇપલાઇનની જેમ, આ કામ Moonshotનું Fireworks પર ચાલતું ઓપન મોડેલ Kimi K3એ કર્યું: માપણી, મોડેલિંગ, કોડ અને ચકાસણી. વ્યક્તિએ સ્ક્રીનશૉટ આપ્યો, એક પ્રશ્નનો જવાબ આપ્યો અને વાસ્તવિક iPad પર તેનો અહેસાસ તપાસ્યો.

સ્પેસિફિકેશન એક સ્ક્રીનશૉટ છે

સ્થિર છબી તમને કહી શકતી નથી કે કોઈ સ્ટ્રોક પાતળો કેમ છે. તે ફક્ત કેટલો પાતળો છે અને ક્યાં છે એટલું બતાવી શકે છે. તેથી પહેલું પગલું માપણીનું હતું. અમે સ્ક્રીનશૉટને પંક્તિ-દર-પંક્તિ અને કૉલમ-દર-કૉલમ સ્કૅન કર્યો, દરેક સ્ટ્રોકની મધ્યરેખા કેટલી ખસે છે તે નોંધ્યું જેથી તેની દિશા મળી શકે, અને પછી તે ખૂણાના સાઇન વડે સ્કૅન કરેલી પહોળાઈને વાસ્તવિક પહોળાઈમાં ફેરવી:

સ્ટ્રોકદિશાવાસ્તવિક પહોળાઈ
“l” નો ઊર્ધ્વગામી ભાગ, “pencilkit”≈ 78°27.3 px
“k” નો દાંડો, “pencilkit”≈ 90°28 px
力 નો ડાબી તરફ ઉતરતો ઝાટકો≈ 66°25.7 px
કર્સિવના જોડાણ-સ્ટ્રોક≈ 8°11 px
ચીની આડા સ્ટ્રોક (横)≈ 0°6–11 px

જાડા અને પાતળા સ્ટ્રોકનું પ્રમાણ ≈ 2.5 છે. 66°ના બિંદુ સાથે ને ગોઠવતાં મળે છે — સાથે સંબંધ લગભગ રેખીય છે અને ઊભી ધરી પર મહત્તમ થાય છે. હકીકતમાં આ તિરછો નિબ છે: આડી ચીરો, જેને આડું લખાણ ક્યારેય ખોલતું નથી.

પહેલું સંસ્કરણ: દિશાથી પહોળાઈ

પહેલું મોડેલ સ્વાભાવિક પસંદગી હતું. દરેક ઇનપુટ બિંદુ માટે દિશા ગણવામાં આવતી, ગોઠવાયેલી વક્રરેખા વડે દિશાને પહોળાઈમાં ફેરવવામાં આવતી અને કૅપ્ચર સમયે પરિણામ બિંદુની ત્રિજ્યામાં સંગ્રહાતું. દિશાનો અંદાજ કારણાત્મક રીતે લેવાયો — આર્કના છેલ્લાં થોડા બિંદુઓનું ઘટતા વજનવાળું ઘાતાંકીય સરેરાશ, દ્વિ-કોણ અવકાશમાં ગણાયેલું, જેથી ગતિની દિશા ઉલટાય ત્યારે અંદાજ રદ ન થાય. ફક્ત અગાઉના બિંદુઓ વપરાય છે, તેથી જીવંત સ્ટ્રોક અને કમિટ થયેલો સ્ટ્રોક બાઇટ-દર-બાઇટ સરખા રહે છે.

બિલ્ડરે પોતાની યુનિટ ચકાસણી પાસ કરી: કૃત્રિમ આડા, ઊભા, 45° અને દિશા-પલટાના માર્ગોએ સૈદ્ધાંતિક પહોળાઈઓ — 0.99, 2.52, 2.00 અને 0.99 પૉઇન્ટ — સંગ્રહિત કરી. રેન્ડરિંગ માટે એક પણ નવો કોડ જરૂરી નહોતો: પહેલેથી ત્રિજ્યા ધરાવતો સ્ટ્રોક ગોળ સ્ટૅમ્પની સાંકળ જ છે અને અમારી point-sprite પાઇપલાઇન તેને પહેલેથી દોરી શકતી હતી.

iPad પર વ્યક્તિએ તેને નકારવામાં લગભગ દસ સેકન્ડ લીધા: “આ કલા-પેન છે, વોટર પેન નથી.”

એક ચિત્રમાં બે શક્ય સમજૂતીઓ

તે ખોટું કેમ લાગ્યું? બે સંભવિત સમજૂતીઓ હતી અને સ્ક્રીનશૉટ તેમને અલગ કરી શકતો નહોતો:

  • દિશા-લૉક. નિબની ભૂમિતિ હાથ કંઈ પણ કરે, આડા સ્ટ્રોક પાતળા અને ઊભા સ્ટ્રોક જાડા રાખે છે. પહેલું સંસ્કરણ આ જ અમલમાં મૂકતું હતું.
  • દબાણ અને ઝડપ. પેન દબાણથી ચાલે છે અને નમૂનાનો દેખાવ માત્ર હસ્તલિખિત લખાણની ગતિશીલતા છે: નીચે જતા સ્ટ્રોક પર સ્વાભાવિક રીતે વધુ દબાણ પડે છે, જ્યારે જોડાણ-સ્ટ્રોક સ્વાભાવિક રીતે ઝડપી અને હળવા હોય છે.

બંને સમજૂતીઓ પાતળા આડા અને જાડા ઊભા સ્ટ્રોકવાળો સ્ક્રીનશૉટ બનાવે છે. તફાવત એ છે કે આડા સ્ટ્રોક પર જોરથી દબાવો ત્યારે શું થાય છે. પહેલું સંસ્કરણ તેને પાતળો જ રાખે છે. દબાણ-સંવેદનશીલ પેન તેને જાડો બનાવે છે. તેથી અમે વ્યક્તિને એક પ્રશ્ન પૂછ્યો: શું જોરથી દબાવેલો આડો સ્ટ્રોક જાડો થવો જોઈએ?

“ના. આડા સ્ટ્રોક પાતળા જ રહે છે.”

દિશા-લૉકની પુષ્ટિ થઈ. પરંતુ કંઈક બીજું ખોટું હતું, કારણ કે પહેલું સંસ્કરણ પણ દિશા-લૉક ધરાવતું હતું.

જવાબ સ્ટ્રોકના છેડાઓમાં હતો

આગળનો સંકેત ઊર્ધ્વગામી સ્ટ્રોકના ટોચે હતો. નમૂનામાં “l” અને “k”ના દાંડાઓને મોટાં કરીને જોતા બે વાતો દેખાઈ: સીધો સ્ટ્રોક શરૂઆતથી અંત સુધી એક જ પહોળાઈ રાખે છે, અને સ્ટ્રોકના છેડા સપાટ ત્રાંસા કાપ છે — છિન્ની જેવા નિબનો આકાર ઉપર ઉઠતી વખતે બને છે. ગોળ બિંદુ નહીં. દબાણથી થતી પાતળાઈ નહીં.

નમૂનામાંથી બે હસ્તલિખિત ઊર્ધ્વગામી દાંડાઓનો નજીકનો કટ; બંને ઉપર સપાટ ત્રાંસા કાપથી પૂરા થાય છે અને દાંડાની આખી લંબાઈમાં જાડાઈ સમાન રહે છે.

“કલા-પેનનો અહેસાસ”નો સાચો અર્થ આ જ હતો. પહેલું સંસ્કરણ નમૂનાનો દેખાવ મોડેલ કરતું હતું — અંદાજિત દિશાના ફંક્શન તરીકે પહોળાઈ — પણ પેનને નહીં. દિશા-અંદાજક એક સેન્સર છે: અવાજવાળા ઇનપુટ પર કંપે છે, ખૂણાઓ પાસે મોડું પડે છે અને દરેક સ્ટ્રોકના છેડાને ગોળ કરે છે. સાચા નિબને આમાંથી કોઈ સમસ્યા નથી, કારણ કે તે કંઈ ગણતરી કરતું નથી. પહોળાઈ ભૂમિતિ છે.

બીજું સંસ્કરણ: એલિપ્સ આકારનું નિબ

અંતિમ મોડેલમાં દિશા-અંદાજક જ નથી. નિબ દિશાનુસાર ગોઠવાયેલી એલિપ્સ છે: લાંબી ધરી આડી છે અને ટૂંકી ધરી નિશ્ચિત છે. આ એલિપ્સના સ્ટૅમ્પ સ્ટ્રોકના માર્ગ પર ગીચ રીતે મૂકવામાં આવે છે અને બાકીનું બધું ભૂમિતિમાંથી મળે છે:

  • આડો સ્ટ્રોક ખુલ્લી ધાર પર આગળ વધે છે, તેથી તેની પહોળાઈ હંમેશા રહે છે — કોઈપણ દબાણે સ્થિર પાતળી રેખા. બરાબર પુષ્ટિ થયેલી સ્પેસિફિકેશન.

  • ઊભો સ્ટ્રોક આખી લાંબી ધરીને પાર કરે છે: , જાડો છેડો.

  • ત્રાંસો સ્ટ્રોક ગતિની દિશાને લંબ દિશામાં એલિપ્સની કૉર્ડની પહોળાઈ લે છે,

  • સ્ટ્રોકના છેડા એલિપ્ટિકલ કાપ છે — નમૂનામાં દેખાતા સપાટ નિબ-આકારના છેડા, કોઈ વધારાના કામ વિના.

  • દબાણ ફક્ત લાંબી ધરીને સ્કેલ કરે છે, , તેથી નીચે જતા સ્ટ્રોકમાં શાહીનું પ્રમાણ વધે છે અને આડો સ્ટ્રોક ક્યારેય જાડો થઈ શકતો નથી.

નમૂનાના માપના આધારે અમે pt અને pt રાખ્યા, એટલે એ જ 2.5નું પ્રમાણ. આર્ક પર સ્ટૅમ્પ એકબીજાથી 0.5 પૉઇન્ટ દૂર છે; 0.55 પૉઇન્ટની ટૂંકી ત્રિજ્યા સાથે સૌથી ખરાબ સ્થિતિમાં ધારનું તરંગન લગભગ એક પિક્સેલના દસમા ભાગ જેટલું રહે છે.

રેન્ડરિંગ માટે એક નવો fragment shader જ જરૂરી હતો અને બીજું કશું નહીં. Vertex format — position, diameter, color — પહેલેથી બધું વહન કરતું હતું: diameter લાંબી ધરી છે અને short axis per-pass uniform છે. Shader અમારા ગોળ સ્ટૅમ્પ જેવી જ half-pixel coverage ramp સાથે ellipse SDFનું મૂલ્યાંકન કરે છે; તેથી Core Graphicsના સંદર્ભ અમલીકરણ (fillEllipse પ્રતિ સ્ટૅમ્પ) સાથે પિક્સેલ-દર-પિક્સેલ સરખામણી કરી શકાય છે. ચકાસણી સામાન્ય ગેટમાંથી પસાર થઈ: બે ફાઉન્ટેન-પેન સ્ટ્રોક ધરાવતું કૃત્રિમ corpus બંને રીતે રેન્ડર કરીને પિક્સેલ-દર-પિક્સેલ સરખાવવામાં આવ્યું — માળખાકીય તફાવત શૂન્ય, અને નમૂનાથી ચકાસેલો આડો સ્ટ્રોક બંને રેન્ડરરમાં 12 px માપાયો.

એક જ હસ્તલિખિત શબ્દ “fountain”ના બે રેન્ડરિંગ બાજુબાજુ: ડાબે દિશા પ્રમાણે માપેલા વ્યાસવાળા ગોળ સ્ટૅમ્પથી બનેલું સંસ્કરણ, જેમાં ગોળ છેડા છે; જમણે એલિપ્સ સ્ટૅમ્પવાળું સંસ્કરણ, જેમાં નિબથી કપાયેલા સપાટ છેડા અને વધુ સ્થિર પહોળાઈ છે.

પહેલું સંસ્કરણ ડાબે અને બીજું જમણે. એ જ હસ્તલિખિત ઇનપુટ, એ જ પાઇપલાઇન. છેડા આખી વાત કહી દે છે.

iPad પર નવી પેન તરત પાસ થઈ: “好,很好” — સારું. ખૂબ સારું.

નિષ્ફળ પ્રયાસને સાચવી રાખવો

પહેલું સંસ્કરણ કચરાપેટીમાં ગયું નહીં. તે રસપ્રદ બ્રશ છે — બસ વોટર પેન નથી. તેથી તેને નવા પ્રાયોગિક બ્રશ મેનૂની પહેલી એન્ટ્રી તરીકે, વ્યક્તિએ આપેલા નામ હેઠળ, મોકલવામાં આવ્યું: 漏水的圆珠笔, એટલે કે લીક થતો બોલપેન. ટૂલબારમાં ફ્લાસ્ક આકારનું બટન ઉમેરાયું, જે પ્રયોગોની ટેક્સ્ટ યાદી ખોલે છે; આગળનો પ્રયોગ ઉમેરવા રજિસ્ટ્રીમાં એક પંક્તિ પૂરતી છે. નકારાયેલું મોડેલ સ્પષ્ટ રીતે લેબલ કરેલા પ્રયોગ તરીકે મોકલી શકાય, તો એ વેડફાયેલું કામ નથી.

એક સાંજના ચક્રો

આખું ચક્ર — માપવું, મોડેલ બનાવવું, બનાવવું, ઉપકરણ પર અજમાવવું, પ્રશ્ન પૂછવો, ફરી મોડેલ બનાવવું, ફરી બનાવવું અને ચકાસવું — એક સાંજમાં પૂરું થયું. Fireworks પર Kimi K3એ લૂપનો આખો તકનીકી ભાગ સંભાળ્યો: માપણી સ્કૅન તૈયાર કર્યાં, બીજી વાર અનુમાન કરવાને બદલે ભેદ પાડતો પ્રશ્ન સૂચવ્યો, પુરાવા બદલાતાં પોતાનો દિશા-અંદાજક કાઢી નાખ્યો અને ઍપને સ્પર્શતાં પહેલાં pixel-diff harness વિસ્તૃત કર્યું. Fireworksની ઇન્ફરન્સ ઝડપે લૂપને ઇન્ટરૅક્ટિવ રાખ્યો — લાંબા Metal અને Swift diffs, પિક્સેલ-વિશ્લેષણ સ્ક્રિપ્ટો અને corpus tooling એટલી ઝડપથી આવ્યા કે બાકી રહેલો અવરોધ માનવીય નિર્ણય જ રહ્યો.

સહયોગની રીત Metal પાઇપલાઇન વિશેના લેખ જેવી જ હતી અને ફરી સફળ રહી: મોડેલ ઝડપી અને ચોક્કસ છે; વ્યક્તિ સ્વાદ અને શરૂઆતથી અંત સુધીની ચકાસણી સંભાળે છે. અહેસાસ આધારિત પ્રતિસાદનું એક વાક્ય — “કલા-પેન, વોટર પેન નહીં” — મોડેલને ચોક્કસ મોડેલિંગ ભૂલ શોધીને સરળ ડિઝાઇનથી બદલવા પૂરતું હતું.

સાચું મોડેલ ખોટા કરતાં નાનું નીકળ્યું. બીજું સંસ્કરણ પહેલા કરતાં ઓછા ચલ ભાગો સાથે મોકલાયું — કોઈ અંદાજક નહીં, કોઈ સ્મૂધિંગ વિન્ડો નહીં અને કોઈ ગોઠવાયેલો ઘાતાંક નહીં. નિબ પહોળાઈની ગણતરી કરતું નથી. નિબ જ પહોળાઈ છે.