4 पॉइंट द्वारा GN⁺ 2023-12-08 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • जैसे-जैसे वेब illustration सपाट vector से आगे बढ़कर noise texture और lighting·shading इस्तेमाल करने की दिशा में फैल रही है, इसे हल्के और reusable SVG के रूप में लागू करने का तरीका महत्वपूर्ण हो गया है
  • मुख्य लक्ष्य है साधारण shapes में texture वाला shadow effect जोड़ना, और उसे Svelte या React component में ले जाकर color और shape बदलकर इस्तेमाल करने योग्य बनाना
  • बुनियादी संरचना में <defs> में shape को एक बार define किया जाता है, फिर <use> से reuse किया जाता है, और masklinearGradient से color पर कम निर्भर gradient mask बनाया जाता है
  • दानेदार texture <feTurbulence> आधारित SVG filter से बनाया जाता है, और <feComposite>, <feColorMatrix>, <feBlend> को जोड़कर चुने गए fill color के साथ mix किया जाता है
  • नतीजा इच्छित texture के काफ़ी करीब पहुँचा, लेकिन Safari rendering difference अभी भी मौजूद है, इसलिए browser-वार rendering और अधिक जटिल illustration पर लागू करने के लिए अतिरिक्त adjustment की ज़रूरत है

सिर्फ कोड से SVG में noise texture जोड़ना

  • हाल के web design में vector illustration लगातार इस्तेमाल हो रही है, लेकिन साफ-सुथरे flat shapes की तुलना में खुरदुरी दानेदार texture वाली lighting·shading style ज़्यादा नज़र आ रही है
  • इस तरह की style को illustration program से SVG के रूप में export किया जा सकता है, लेकिन texture raster के रूप में शामिल हो सकती है या vector का आकार बड़ा हो सकता है
  • लक्ष्य है केवल सामान्य SVG spec का उपयोग करके noise वाली textured shadow effect बनाना, और संरचना को component बनाना आसान रहे ऐसा रखना
  • reuse के लिए इसे इस तरह बनाया गया है कि shape और color बदलने पर भी वही तरीका काम करे

बुनियादी shape और gradient

  • circle या rectangle जैसी SVG basic shapes आसानी से बनाई जा सकती हैं, लेकिन reusable component में fixed-color gradient काफ़ी नहीं होता
  • base color के अनुसार बदलने वाला gradient बनाने के लिए mask का उपयोग किया जाता है
    • SVG mask काले और सफेद के आधार पर दिखने या छिपने वाले क्षेत्रों को नियंत्रित करता है
    • तरीका थोड़ा भ्रमित कर सकता है, लेकिन इसे सरल उदाहरण से शुरू किया जा सकता है
  • अगर एक ही circle shape को कई बार इस्तेमाल करना हो, तो <defs> के अंदर <circle id="shape"> define करके <use href="#shape"> से reference किया जाता है
  • यह तरीका दोहराव कम करता है और shape definition को एक जगह रखने वाली DRY संरचना देता है

noise texture बनाने का तरीका

  • gradient के ऊपर texture चढ़ाने के लिए SVG filter का उपयोग किया जाता है
  • noise generation का काम <feTurbulence> करता है
    • <feTurbulence> कृत्रिम texture बनाने वाला SVG filter primitive है
    • मनचाहा एहसास पाने के लिए कई values को adjust करना पड़ता है
  • अंतिम filter कई चरणों से गुज़रकर texture को color के साथ blend करता है
    • <feTurbulence type="fractalNoise" baseFrequency="19.5" numOctaves="10"> से noise बनाया जाता है
    • <feComposite> से turbulence result को SourceAlpha के भीतर composite किया जाता है
    • <feColorMatrix type="luminanceToAlpha"> से color variation कम किया जाता है
    • <feBlend mode="color-burn"> से original graphic के साथ composite किया जाता है
  • filter को अंतिम <use> element पर filter="url('#noise')" से लागू किया जाता है

अंतिम SVG संरचना

  • अंतिम example में <defs> के अंदर shape, filter, mask और gradient को साथ में define किया गया है
  • gradient को linearGradient id="fade" से बनाया गया है
    • 0% बिंदु पर काले रंग के साथ stop-opacity="0.6" का उपयोग होता है
    • 65% और 75% बिंदुओं पर सफेद रंग का उपयोग करके opacity को क्रमिक रूप से adjust किया जाता है
  • अंतिम shape पर fill color, mask और filter एक साथ लागू होते हैं
    • fill="hsl(337, 92%, 69%)"
    • mask="url(#gradient)"
    • filter="url('#noise')"
  • color जोड़कर और gradient को अधिक सूक्ष्म रूप से adjust करके मनचाहे visual effect के करीब परिणाम हासिल किया जाता है
  • पूरा परिणाम Full Demo में देखा जा सकता है, और implementation code repository में प्रकाशित है

परिणाम और सीमाएँ

  • अतिरिक्त प्रयोगों के बाद संतोषजनक illustration बनाई गई, लेकिन परिणाम अभी पूरी तरह परिपूर्ण नहीं है
  • खासकर Safari में यह दूसरे browsers से अलग render होता है
  • संदर्भ के रूप में देखी गई जटिल illustration की तुलना में यह अभी भी सरल है, लेकिन और निखारने पर इसे अधिक स्थितियों में इस्तेमाल किया जा सकता है
  • 7 दिसंबर 2023 को जोड़ी गई अतिरिक्त जानकारी के अनुसार, Hacker News पर submit करने के बाद Jimmy Chion की 2021 की CSS-Tricks post Grainy Gradients के बारे में पता चला
  • उस लेख में पहुँची हुई technique इस तरीके से मिलती-जुलती लगती है, इसलिए उसे पूरक संदर्भ के रूप में भी देखा जा सकता है

2 टिप्पणियां

 
ndrgrd 2023-12-09

उम्मीद के मुताबिक, Safari ने फिर निराश नहीं किया! इसे 2020s का IE कहना भी गलत नहीं होगा।

 
GN⁺ 2023-12-08
Hacker News की राय
  • हाल ही में SVG के साथ काम करते हुए मैं एक drop shadow डालना चाहता था, जो canvas से बनाना मुश्किल था, लेकिन Safari में SVG के अंदर CSS drop shadow काम नहीं करता, इसलिए SVG का native drop shadow filter इस्तेमाल करना पड़ा, और उसका नतीजा भी दूसरे browsers से अलग दिखा
    इसका ठोस उदाहरण https://www.einarmagnus.net/pages/logo पर है, जहां JavaScript से Safari detect करके SVG version चालू और CSS version बंद किया गया है
    “recursive yin-yang” background https://einarmagnus.net/blog/2020/01/22/finding-the-logo पर है
    texture के साथ और experiment करना चाहता हूं, लेकिन Safari में इसका इतना अलग दिखना परेशान करता है। सोचता हूं कि कभी SVG interpretation के तरीके converge होंगे या नहीं

    • फिलहाल तो convergence होता नहीं दिखता। दुर्भाग्य से पूरे SVG spec को implement करने वाली कोई जगह नहीं है, और SVG 2 तक आते-आते दूरी खासकर बहुत बढ़ जाती है
      इस विषय पर https://razrfalcon.github.io/notes-on-svg-parsing/ पढ़ने लायक है
      SVG library bug reports में “मेरा SVG ठीक से render नहीं हो रहा” जैसा वाक्य अक्सर दिखता है, लेकिन बात यह है कि सही तरह से rendered SVG जैसी कोई चीज़ असल में होती ही नहीं। मतलब यह है कि text, filters, animation जैसी advanced features इस्तेमाल करना शुरू करते ही अलग-अलग renderers में चीज़ें आसानी से टूट जाती हैं
    • ‘logo’ page पर अगर कोई सिर्फ default waveform देखकर निकल रहा है, तो दाईं ओर नीचे dropdown में कुछ presets दबाकर देखना अच्छा रहेगा
      parameters को थोड़ा-सा बदलने भर से scorpion, balance, spruce जैसे काफी अलग design निकल आते हैं, यह बढ़िया है
  • लेखक जिस term को खोज रहे थे, वह dithering के ज्यादा करीब है। CSS-Tricks का “Grainy Gradients” भी यही technique समझाता है
    https://css-tricks.com/grainy-gradients/
    CSS से कुछ मिलता-जुलता करने का एक alternative भी है, लेकिन वह पूरी image पर लागू होता है
    https://github.com/tomren1/dither-with-css

    • यह असल में बस noise के ज्यादा करीब है, और अधिक सटीक कहें तो Perlin noise family के साथ “color burn” blending mode का combination है। gradient के ऊपर रखने पर यह dithering जैसा दिखता है, लेकिन dithering नहीं है
      dithering वह technique है जिसमें smooth high-color-depth image को सीमित colors में quantize करते समय banding कम करने के लिए हर pixel को ऊपर या नीचे की value में से एक probabilistically चुना जाता है। जहां desired color ठीक-ठीक मौजूद हो, वहां यह noise जैसा दिखे, जरूरी नहीं
      यहां तो बस uniform noise texture बनता है, और यह असल banding को कम नहीं करता। aesthetic purpose के लिए यह असली dithering से बेहतर दिखता है
      हालांकि dithering की तरह यह defects छिपाकर और perceived sharpness बढ़ाकर image quality बेहतर दिखाने का effect दे सकता है
    • dithering एक वास्तविक technical method है जिसका final effect मिलता-जुलता है, लेकिन अपने-आप में इसका मतलब graininess जोड़ना नहीं है, और यह example भी dithering से नहीं बना है
      लेखक शायद “flat”, “skeuomorphic”, “italian style” जैसे visual style को बुलाने वाला design term खोज रहे हैं
      geometric forms और graininess के combination को देखकर Memphis style याद आता है
    • अगर सीमित palette से color range को ज्यादा व्यापक दिखाने की कोशिश नहीं है, तो पता नहीं इसे सचमुच dithering कहा जा सकता है या नहीं
      इसके बजाय vintage travel poster art याद आता है। उदाहरण: https://www.graphicart-news.com/wp-content/uploads/2012/09/2...
    • dithering से संबंध तो है, लेकिन निजी तौर पर यह मुझे stippling के ज्यादा करीब लगता है [0]
      [0] https://en.wikipedia.org/wiki/Stippling
    • थोड़ा शर्मिंदगी वाली बात है। मुझे उस लेख का link डालने के लिए post update करनी चाहिए
      इसे बनाते समय मैंने वह सच में नहीं देखा था, और खुद try करते-करते उसी conclusion पर पहुंचा
  • याद आता है कि film photographers और filmmakers film grain हटाने की कोशिश करते थे, जबकि digital photographers उसे वापस जोड़ना चाहते दिखते हैं। दूसरे की थाली में घी ज्यादा लगता है
    पूरी तरह digital और sterile चीज़ों के बीच, इस page के examples काफी आकर्षक लगते हैं

    • बहुत ज्यादा generalize न करना बेहतर होगा। digital video और उसके बाद digital photography के आने के बाद से, noise घटाने वाले, हटाने वाले, उसकी नकल करने वाले, और उसे जानबूझकर इस्तेमाल करने वाले लोग हमेशा साथ-साथ मौजूद रहे हैं
      noise अपने-आप में समस्या नहीं थी; असली सवाल हमेशा यह था कि वह बहुत ज्यादा है या नहीं
    • क्या Foveon X3 ने इसे कुछ हद तक हल नहीं कर दिया था? film जैसा, लेकिन digital तरीके से
  • क्या कहीं ऐसा मटेरियल है जिसमें यहまとめ किया गया हो कि हर implementation में कौन-सी चीज़ टूटती है? मुझे SVG से अपनी मानसिक सेहत बचाए रखने का तरीका जानना है
    हाल ही में मैंने एक जटिल conference poster को SVG में बनाने की गलती कर दी, और अब यह हर browser और program में अलग-अलग render होता है
    https://kxygk.github.io/imergination/
    बनाते समय मेरा अनुभव यह रहा: SVG को include या link तो किया जा सकता है, लेकिन अगर उसके अंदर फिर कोई दूसरा SVG हो तो वह काम नहीं करता। उदाहरण के लिए poster → diagram → कई plots/maps जैसी structure हो, तो sub-image बदलने पर dynamically update होने वाला SVG practically impossible है
    Web browser “security” reasons से embedded/linked images को अपनी मर्ज़ी से display न भी करें। ऊपर वाले link के SVG को अलग tab में खोलने पर यह ठीक से display नहीं होता: https://raw.githubusercontent.com/wiki/kxygk/imergination/ag...
    जटिल SVG को PDF में बदलना भी बिना mismatch के handle करना मुश्किल है, और memory भी खत्म हो सकती है। हर SVG-to-PDF converter का result अलग होता है
    Inkscape जैसे कई implementations embedded SVG को मनमाने ढंग से raster graphics की तरह treat कर देते थे, और आखिर तक यह pinpoint नहीं कर पाया कि ऐसा कब होता है। PNG में render करते समय Inkscape द्वारा DPI setting को sub-images तक propagate न करने की समस्या भी थी

  • बढ़िया है। लगता है Inkscape Filters menu के कई effects के ज़रिए इस तरह का noise जोड़ना support करता है। Plain SVG में export करके code देखा तो confirm हुआ कि यह feTurbulence इस्तेमाल करता है
    तुलना के लिए Affinity Designer 2 का noise fill भी try किया, लेकिन exported SVG में noise base64 JPEG image के रूप में embedded था

    • अभी PC के सामने नहीं हूँ इसलिए खुद check नहीं कर सकता, लेकिन जानना चाहता हूँ कि क्या यह एक noise texture embed करके उसे कई बार इस्तेमाल करता है, या noise इस्तेमाल करने पर हर बार नया texture बनाता है
      Adobe license को justify करना मुश्किल है और InkScape भी मुझे खास suit नहीं करता; ऐसे में इन अजीब quirks को छोड़ दें तो Designer एक perfect alternative था
    • Affinity Designer 2 Adobe Creative Cloud न लेने के alternative के रूप में काफी अच्छा था, लेकिन SVG को manually ठीक करने की ज़रूरत सचमुच बहुत बार पड़ती थी
  • “ApeFest” website[1] में भी dynamic noise था, इसलिए मैंने CSS देखी। वही event site जिसने attendees की retinas को UV से जला दिया था
    असल में यह tiled PNG overlay[2] इस्तेमाल करता है और CSS animation से उसे “random” जैसा हिलाता है। edit: असल में लगता है यह JS से move होता है। काफी low-tech है, लेकिन काम करता है
    [1] https://apefest.com/
    [2] https://framerusercontent.com/images/rR6HYXBrMmX4cRpXfXUOvpv...

    • apefest effect CPU बहुत इस्तेमाल करता है, और उतनी ही energy भी
  • मैं ऐसे SVG filters कई बार इस्तेमाल करना चाहता था, लेकिन समस्या यह है कि engine और zoom scale के हिसाब से presentation काफी बदल जाती है
    इसलिए इन्हें केवल उन subtle effects के लिए इस्तेमाल किया जा सकता है जहाँ inaccuracy बहुत मायने नहीं रखती, और अंत में अफसोस के साथ बार-बार raster पर लौटना पड़ता है
    साथ ही pixel-level पर काम करने की वजह से feDisplacementMap जैसी चीज़ें anti-aliasing खराब कर देती हैं, और जिन स्थितियों में इन्हें इस्तेमाल करने का मन होता है उनमें से लगभग आधी को बिगाड़ देती हैं

  • Perlin noise और उसका successor fractal noise realism या organic feel जोड़ने में cost के मुकाबले जबरदस्त असर देते हैं
    उदाहरण के लिए Aladdin (1992) में Cave of Wonders से escape वाले scene में इसे बहुत प्रभावी ढंग से इस्तेमाल होते देखा जा सकता है

  • मुझे नहीं पता यह असल में कैसा दिखना चाहिए, लेकिन मेरे phone पर यह noise के बिना सिर्फ smooth gradient जैसा दिखता है

    • यहाँ भी वही। Android Chrome इस्तेमाल कर रहा हूँ
    • लगता है Android Chrome code के अंदर की किसी functionality को support नहीं करता
  • effect पसंद आया, लेकिन क्या इसे zoom scale से independent बनाने का कोई तरीका है?
    इसी से related, लगता है यह randomness भी जोड़ता है; क्या इसमें seed देने का कोई तरीका है? जैसे किसी specific size पर एक correct rendering result define किया जा सके तो अच्छा होगा

    • लेखक हूँ। संभव है। SVG का base algorithm और implementation seed value लेते हैं: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/s...
    • दूसरे जवाब की तरह seed attribute है, और random function algorithm भी spec में C code की 186 lines में defined है[0], इसलिए theory में अलग-अलग implementations में एक जैसा result आना चाहिए
      हालांकि code देखने पर इसमें floating-point operations इस्तेमाल होते हैं, और मेरी जानकारी में यह implementation-defined होता है, इसलिए platforms के बीच अलग behavior होने की संभावना दिखती है
      [0]: https://drafts.fxtf.org/filter-effects/#elementdef-feturbule...