2 पॉइंट द्वारा GN⁺ 2024-03-01 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • LUT (लुकअप टेबल) पहले से गणना किए गए मानों को तालिका की तरह संदर्भित करने का तरीका है, और इसका उपयोग ब्लैक-एंड-व्हाइट थर्मल इमेज को colorize करने से लेकर game object variations और video color correction तक व्यापक रूप से होता है
  • WebGL उदाहरण दिखाता है कि video frames को GPU पर 2D texture के रूप में अपलोड करने के बाद, pixel-by-pixel रंग तय करने वाले Fragment Shader में tinting, 1D LUT और 3D LUT कैसे लागू किए जाते हैं
  • 1D LUT brightness value [0.0 - 1.0] को color array coordinate के रूप में इस्तेमाल करके black-and-white input को RGB में बदलता है, और GPU की bilinear filtering छोटे LUT में भी intermediate values को स्वाभाविक रूप से interpolate करती है
  • Valve के Left 4 Dead उदाहरण की तरह, tinting और LUT का उपयोग सीमित texture memory के भीतर cars, zombie skin और clothing color variations बनाने के लिए किया जाता है
  • LUT अतिरिक्त texture read cost लाता है, लेकिन gamma correction जैसी महंगी calculations को पहले से store करने या external color-correction workflow को real-time graphics में लाने का व्यावहारिक tool है

Graphics programming में LUT क्या करता है

  • लुकअप टेबल (LUT) वह तरीका है जिसमें values को पहले से calculate करके rows या table में store किया जाता है और जरूरत पड़ने पर refer किया जाता है
  • Graphics programming में यह सरल structure कई visual effects में बदल जाता है
    • Black-and-white video को color में बदलना
    • Color correction और styling लागू करना
    • Video games में object variations को efficient बनाना
  • उदाहरण WebGL का उपयोग करता है, लेकिन वही techniques DirectX, OpenGL, Vulkan, Unity और scientific data visualization पर भी लागू होती हैं
  • Demo video Panasonic GH6 और TESTO 890 thermal imaging camera captures हैं, और processing device से बाहर नहीं जाती बल्कि GPU पर locally process होती है

WebGL pipeline और tinting

  • Thermal imaging camera output black-and-white video है, और हर frame WebGL के जरिए GPU को 2D texture के रूप में भेजा जाता है
  • Fragment Shader वह code है जो output के हर fragment के लिए final color तय करता है
    • उदाहरण में texture2D(video, tex).rgb से current position का video color पढ़ा जाता है
    • WebGL 1.0 का final output gl_FragColor में RGBA के रूप में लिखा जाता है
  • Tinting texture color को किसी खास color से multiply करके tint लगाने का तरीका है
    • उदाहरण में videoColor * vec3(1.0, 0.5, 0.0) से orange color multiply किया जाता है
    • White orange बन जाता है, और black पर 0 multiply होता है, इसलिए वह black ही रहता है
  • इस context में tinting की multiplication cost मापना मुश्किल हो सकता है
    • Memory से texture fetch करने की cost multiplication से कहीं ज्यादा होती है
    • कई threads parallel चलने पर, एक pixel के texture read का इंतजार करते समय दूसरे pixel की multiplication हो सकती है
    • यह tinting से होने वाले फर्क की व्याख्या है, इसका मतलब यह नहीं कि पूरी performance optimization खत्म हो गई है

Valve का tinting उपयोग

  • Valve Software के Left 4 Dead ने car variations बनाने के लिए tinting का उपयोग किया
  • हर car type और color के लिए अलग texture रखने का तरीका texture memory budget से ज्यादा हो सकता है
  • Valve ने अतिरिक्त mask texture का उपयोग करके cars के painted areas को हर instance में अलग color से tint किया
    • एक color texture 3 car models में share किया गया
    • दो textures की cost में 4 car models और practically unlimited color variations बनाए जा सकते हैं
  • Source Engine में cars ही नहीं, मूल रूप से हर चीज को tint किया जा सकता है

1D LUT से black-and-white values को colors में बदलना

  • 1D LUT एक number array है, और अगर यह RGB image है तो colors की one-dimensional array है
  • Black-and-white video की brightness value को LUT के X-axis coordinate के रूप में इस्तेमाल करके color लाया जाता है
    • Video brightness value की range [0.0 - 1.0] होती है
    • 0.0 black LUT के left-side color में, और 1.0 white LUT के right-side color में map होता है
    • Intermediate values अपनी corresponding position के color में map होती हैं
  • WebGL 1.0 में 1D texture नहीं है, इसलिए height 1px वाली 2D texture का उपयोग होता है
    • Example code texture2D(lut, vec2(videoColor, 0.5)) जैसा है
    • Input 1D value है और output RGB, इसलिए structure “1D vector in, 3D vector out” है
  • GPU की bilinear filtering texture read के दौरान intermediate values को automatically interpolate करती है
    • 8-bit black-and-white video में brightness के 256 levels होते हैं
    • 1D LUT 32 pixels wide हो तब भी pixels के बीच access linear interpolate होता है
    • सिर्फ 8 pixels की information से भी 256-pixel wide colorful gradient के करीब result बनाया जा सकता है

Colormap selection और perceptual uniformity

  • उदाहरण में matplotlib द्वारा supported colormaps को 1D LUT के रूप में export की गई list शामिल है
  • अगर data में कोई specific structure नहीं है, तो perceptually uniform colormap का उपयोग करना या उस पर आधारित colors सेट करना उचित है
    • viridis family इसका प्रमुख उदाहरण है
  • Perceptually uniform colormap black-and-white में output करने पर भी ठंडे हिस्सों को dark और गर्म हिस्सों को bright बनाए रखता है
  • jet जैसे colormaps, जो मुख्य रूप से सिर्फ hue बदलते हैं और perceived brightness को ignore करते हैं, इस property की guarantee नहीं देते
  • Color vision deficiency वाले लोग भी data को सही तरह interpret कर सकें, यह colormap selection का अहम criterion है

1D LUT की performance और polynomial approximation

  • छोटे 1D LUT की cost आम तौर पर कम हो सकती है, लेकिन tinting की तुलना में consider करने वाली बातें ज्यादा हैं
  • मुख्य performance concern dependent texture read है
    • पहली texture read के result से दूसरी texture read के coordinates तय होते हैं
    • Graphics programming में यह ऐसा pattern है जो कुछ optimizable paths को खत्म कर सकता है
  • GPU में texture cache होता है, और छोटा LUT cache में fit हो सकता है, इसलिए LUT read की cost बहुत कम हो सकती है
  • Fine-grained performance judgment के लिए platform-specific analysis tools चाहिए
    • Nvidia NSight shader stage-wise performance analysis देता है, लेकिन OpenGL support नहीं करता
  • Colormap को polynomial approximation के रूप में implement करने पर LUT texture संभालने की जरूरत नहीं रहती
    • Matt Zucker का ShaderToy viridis approximation Horner’s method के रूप में लिखा गया है
    • c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6))))) जैसी multiply-add operations से color calculate होता है
    • यह वास्तव में LUT से fast है या नहीं, platform-specific analysis के बिना तय करना मुश्किल है

Left 4 Dead 2 में zombie variations

  • Left 4 Dead 2 ने skin और clothing color variations के लिए LUT का उपयोग किया, जहां simple tinting पर्याप्त नहीं था
  • Simple tinting color luminance की पर्याप्त diversity नहीं दे सकता
  • Skin और clothing के लिए कुछ LUTs randomly चुनकर diverse color variations बनाए जाते हैं
    • Artists उपयुक्त color ramp चुनकर final game में शामिल करते हैं
    • एक ही texture से light suit और dark suit, दोनों variations बनाए जा सकते हैं
  • संबंधित पूरा presentation GDC के Shading a Bigger Better Sequel में देखा जा सकता है
  • “Exclusive Masking” एक channel के अंदर दो texture ranges रखने का तरीका है
    • Texture 1 की range 0-128 है
    • Texture 2 की range 128-256 है
    • इसकी cost color precision में कमी है

Calculations को पहले से store करने वाला 1D LUT

  • 1D LUT graphics programming में महंगी calculation cache के रूप में भी इस्तेमाल हो सकता है
  • Gamma correction इसका representative example है
    • Approximation नहीं हो तो pow() function चाहिए
    • खासकर पुराने GPU पर pow() महंगा instruction हो सकता है
    • Standard sRGB piecewise curve इस्तेमाल करने पर branching paths भी जुड़ते हैं
  • Gamma transform को 1D LUT में पहले से calculate करने पर per-pixel calculation skip की जा सकती है
    • इस case में structure “1D vector in, 1D vector out” है
    • 1D LUT अधिकतम 4 color channels output कर सकता है
  • Redshift रात में monitor को orange tint करके eye strain घटाने वाला software example है
    • Monitor के Red, Green, Blue channels की Gamma Ramp बदली जाती है
    • Kelvin Warmth → RGB और extra Gamma calculations को 3 1D LUTs में पहले से calculate किया जाता है
    • संबंधित implementation Redshift source code में है
  • इस तरीके में remapping graphics card के बजाय monitor पर होती है, इसलिए performance impact नहीं होता, लेकिन hardware interface support आजकल अक्सर unstable या broken है
    • Raspberry Pi graphics stack में नए update के बाद related support खो जाने का case रहा है
    • Microsoft SetDeviceGammaRamp के उपयोग को लेकर warning देता है

3D LUT: पूरे RGB space को remap करना

  • 3D LUT पूरे RGB space को एक cube के रूप में represent करता है और सभी possible colors को remap करता है
  • Input RGB 3D vector को output RGB 3D vector में बदलता है, इसलिए structure “3D vector in, 3D vector out” है
  • Red, Green, Blue में से प्रत्येक पर 1D LUT लागू करने से color balance बदला जा सकता है
  • 3D LUT उन transforms के लिए जरूरी है जिन्हें input RGB combination चाहिए
    • Saturation बदलना
    • Hue बदलना
    • Specific color adjustment
    • Color separation
  • 3D LUT आमतौर पर cube shape में होता है, games में strip या square form में store होता है और video editing tools में “Iridas/Adobe” .cube file के रूप में इस्तेमाल होता है

WebGL 1.0 में 3D LUT implement करना

  • उदाहरण का video Panasonic GH6 से shoot किया गया Panasonic V-Log color profile video है
  • V-Log एक log profile है जो ज्यादा dynamic range preserve करता है और जिसकी Gamut और Gamma definitions स्पष्ट हैं
  • WebGL 1.0 3D textures support नहीं करता, इसलिए 3D texture read को दो 2D texture reads और interpolation से implement किया जाता है
  • पुराने example code में cube के Z-axis calculation issue की वजह से colors blue की तरफ shift हो जाते थे, और इसे 2019 में fix किया गया
  • WebGL 1.0, OpenGLES 2, OpenGL 2.1 में OES_texture_3D के बिना compatibility बनाए रखने के लिए latest version का 3D texture sampling code इस्तेमाल करना चाहिए

3D LUT से color-correction workflow लाना

  • 3D LUT में लागू correction उस LUT से गुजरने वाले video या graphics scene पर ज्यों का त्यों लागू होता है
  • उदाहरण में V-Log video और LUT को DaVinci Resolve में import करके process किया गया
    • Panasonic का V-Log to V-709 3D-LUT apply किया गया
    • Contrast और white point correct किए गए ताकि white full-bright बने
    • Corrected LUT को फिर export किया गया
  • Actual video original ही रहता है, और color correction WebGL में LUT के जरिए real time में apply होती है
  • Upload की जाने वाली LUT का same size maintain करना जरूरी है
    • Example constraint 1024px × 32px है
    • 32³px cube shape maintain करनी होती है

Game industry में 3D LUT का उपयोग

  • 3D LUT से game colors को external tools में style करने का तरीका video game industry में जाना-माना standard workflow है
  • सामान्य procedure इस प्रकार है
    • Color-correct करने वाले scene का screenshot लें
    • Screenshot और initialized 3D LUT को Photoshop जैसे tool में साथ खोलें
    • Screenshot और LUT पर वही color correction apply करें
    • 3D LUT वाले हिस्से को crop करके export करें
  • Left 4 Dead ने भी यही तरीका इस्तेमाल किया
  • Photoshop के color-correction tools freely इस्तेमाल किए जा सकते हैं, लेकिन ऐसे filters नहीं जो कई pixels के बीच relationship बदलते हैं
    • blur, sharpen, emboss जैसी convolution family remapped color को blur कर सकती है और unexpected results दे सकती है

Complex color correction को एक LUT में bake करना

  • DaVinci Resolve जैसे color-correction tools complex color transforms और color grade बनाकर 3D LUT के रूप में export कर सकते हैं
  • उदाहरण Kodak 2383 LUT apply करता है, जिसका goal film print look है
    • V-Log gamma video को Cineon Film Log में convert किया जाता है
    • Color space को Rec.709 में convert किया जाता है
    • Film emulation apply की जाती है और gamma को फिर Rec.709 में convert किया जाता है
    • अंत में white point adjust किया जाता है
  • Complex detailed transforms को खुद implement किए बिना, उन्हें एक LUT में bake करके graphics application में लाया जा सकता है
  • Example video article compatibility के लिए 8-bit highly compressed format में है, लेकिन आम तौर पर यह काम 10-bit footage पर किया जाता है
  • LUT size उम्मीद से छोटा इस्तेमाल होता है
    • Panasonic official V-Log to V-709 3D-LUT 33³px size का है
    • Panasonic का in-camera monitoring LUT 17³px इस्तेमाल करता है
    • Panasonic के five-figure dollar price range वाले cinema cameras में भी 17³px इस्तेमाल होता है

Graphics के बाहर LUT examples

  • LUT graphics programming के अलावा भी इस्तेमाल होता है
  • Tomb Raider को Game Boy Advance पर port करने के case में भी LUT का उपयोग हुआ
  • Open source OpenLara engine port में Game Boy Advance पर 3D capability नहीं होने के कारण काफी चीजें software में process होती हैं
  • उनमें से एक integer division implement करने वाला LUT है
  • यह LUT load instruction skip करने के लिए ROM address space की शुरुआत में रखा गया है

1 टिप्पणियां

 
GN⁺ 2024-03-01
Hacker News टिप्पणियाँ
  • अगर lookup table नहीं होती तो शायद यह effect बिल्कुल implement नहीं हो पाता: https://twitter.com/zeta0134/status/1756988843851383181
    मुख्य बात यह है कि इसमें दो lookup tables इस्तेमाल होती हैं। बड़ी table player के आसपास configurable radius के भीतर circular lighting जानकारी store करती है, और हर radius के लिए पूरी एक table होती है। दूसरी table background rows का pseudo-random order रखती है। Torch lighting routine हर बार call होने पर screen का सिर्फ 1/20 हिस्सा update करने जितना ही समय होता है, लेकिन order को थोड़ा randomize कर देने से किनारे smooth दिखते हैं और जो raster scan दिखना चाहिए था वह छिप जाता है। यह order एक grab bag है ताकि rows update से भूखी न रह जाएँ, इसलिए real-time calculation बहुत धीमी होने के कारण table इस्तेमाल की जाती है

    • यह काफ़ी शानदार दिखता है, और मुझे याद आने वाले किसी भी NES game से graphics कहीं बेहतर हैं, इसलिए SNES-level graphics जैसा लगता है। लगता है emulator पर चल रहा है; सोच रहा हूँ क्या वह emulator performance को NES level तक सीमित करता है
    • सच में बहुत बढ़िया game लगता है। सोच रहा हूँ क्या यह Crypt of the Necrodancer से inspired है। यह मेरे पसंदीदा games में से एक है। मैंने सोचा था कि अगर ऐसे mechanics उस समय invent हुए होते तो NES या दूसरे पुराने consoles कितना संभाल पाते; लगता है यह दिखाता है कि यह संभव है
    • 1/20 update इसलिए अच्छा काम करता है क्योंकि lamp के move करने पर tiles के naturally reveal होने का illusion देता है। अच्छा है कि ऐसे effect से काम चल जाता है
    • यह हमेशा interesting होता है कि उसी console के लिए games भी समय के साथ, जैसे-जैसे लोग coding सीखते हैं, बहुत ज्यादा सुंदर होते जाते हैं। जैसे Mario 1 और 3, या N64 के दो Zelda games
    • “rows को update से भूखा न रहने देने के लिए random order को grab bag में रखना” वाले हिस्से के लिए search keyword शायद quasirandom होगा
  • पहली बार मुझे सच में impress करने वाला lookup table effect texture tunnel बनाने के लिए इस्तेमाल होने वाला तरीका था
    screen के हर pixel के लिए screen center से angle और distance बताने वाली lookup table रखी जाती है, और उससे तय किया जाता है कि हर pixel position पर कौन-सा texel रखा जाए। यह 3D geometry tunnel के अंदर move करने जैसा दिखता है, लेकिन cost बहुत कम है, इसलिए pico पर भी संभव है: https://www.lexaloffle.com/bbs/?pid=63818
    पहले मैंने सोचा था कि Stardust ने यह effect इस्तेमाल किया होगा, लेकिन अभी खोजने पर पता चला कि असल में वह background में repeat होने वाली 6-frame animation ही चला रहा था: https://codetapper.com/amiga/sprite-tricks/stardust/

    • अगर color palette को lookup table माना जाए, तो palette cycling भी बहुत common थी और काफ़ी related लगती है
    • इसी principle का advanced उपयोग parallax occlusion mapping (POM) है। इसमें self-shadowing तक संभव है
      https://web.engr.oregonstate.edu/~mjb/cs557/Projects/Papers/Parallax_Occlusion_Mapping.pdf
    • अगर देखना चाहते हैं कि यह कैसे काम करता है, तो demo के नीचे छोटा Code ▽ button है
    • कुछ खास cases की symmetry देखने पर सुविधाजनक solution मिल सकता है
  • Wind Waker अपने unique look को बनाने के लिए कई LUT कैसे इस्तेमाल करता है, इस पर एक video है। BoTW और ToTK भी वही technique इस्तेमाल करते हैं
    https://www.youtube.com/watch?v=mnxs6CR6Zrk

  • मैं article का author हूँ। अगर सवाल हों तो जवाब दे सकता हूँ

    • LUT के use cases शानदार हैं, और इस तरह की चीज़ों को साफ़-सुथरे ढंग से समझाने वाला article देखकर अच्छा लगा। WebGL का इस्तेमाल करके data खुद upload करने की सुविधा देना भी अच्छा है
      हालांकि LUT से color correction introduce करने का तरीका थोड़ा surprising था। article में यह L4D2 द्वारा इस्तेमाल किया गया कोई cool niche solution जैसा लगता है, लेकिन असल में यह लंबे समय से industry standard रहा है और मैंने जिन भी games पर काम किया, उनमें इस्तेमाल हुआ। AAA game NFS (2015) से लेकर Lost in Random जैसे बड़े indie games तक, सब में ऐसा था
    • article अच्छा था, और मैं last section में थोड़ा जोड़ना चाहूँगा। Game Boy Advance integer division को कुछ हद तक support करता था, लेकिन यह hardware-accelerated नहीं था [1]। LUT model performance कारणों से चुना गया होने की संभावना ज्यादा है, और वह decision सही लगता है
      [1] https://www.copetti.org/writings/consoles/game-boy-advance/#operating-system
    • typo की वजह से मैं काफ़ी देर तक confused रहा कि कोई दूसरी plotting library है
      “Here is every single colormap that matlibplot supports,...”
    • animated GIFs बहुत ज्यादा हैं, जिससे झुंझलाहट होती है और ध्यान भटकता है। 2010s वाले unfunny boomer memes भी न हों तो चलेगा। रंग-बिरंगे GIFs बार-बार pop up होते रहते हैं, इसलिए article पढ़ना मुश्किल हो जाता है
  • boring business process वाले area में भी यह हैरान करने वाली हद तक useful है
    अक्सर conditions से भरे codebase को साफ़ lookup table से simplify किया जा सकता है। दिखने में simple चीज़ भी 50,000 rows वाली lookup table बन सकती है, इसलिए शायद यह हमेशा दिमाग में नहीं आता। end users को यह ज्यादा लग सकता है, लेकिन computer को खास फर्क नहीं पड़ता। ऊपर से lookup tables repetitive होती हैं, इसलिए आम तौर पर manage करना आसान होता है, और जब ऐसा नहीं भी हो तब भी वे valuable रहती हैं। end users बिना code changes के configure भी कर सकते हैं। कुल मिलाकर business logic code करते समय बार-बार आने वाले कई scenarios के लिए यह concept खास तौर पर useful है

    • और इस तरह अंत में DSL बन जाती है
    • Double-buffered lookup table वाह!
  • रेट्रो गेम्स में tables का सचमुच बहुत इस्तेमाल होता था। उस समय memory speed बहुत तेज़ थी और processors धीमे थे, इसलिए जितनी ज़्यादा calculations हो सकें उन्हें tables में डाल देना समझदारी थी। जितना ज़्यादा चतुराई से करते, उतना ही शानदार game बना सकते थे

    • यह हमेशा ऐसा नहीं था; शायद इस पर निर्भर करता है कि retro से कौन-सा platform मतलब है। YouTube पर Kaze Emanuar N64 development बहुत करते हैं, और optimization की उनकी लगभग आधी बातें इस बारे में होती हैं कि memory bus हर तरह के optimization को कैसे प्रभावित करती है। Mario 64 में sine function के लिए मौजूदा lookup table को approximation से बदल दिया गया था, क्योंकि approximation ज़्यादा तेज़ और पर्याप्त रूप से सटीक था। सटीक कहें तो अलग-अलग उद्देश्यों के लिए दो approximations थे
      मुझे वह channel पसंद है। अपने mod को तेज़ चलाने के लिए उन्होंने Mario 64 के पूरे code को ठीक-ठाक किया और stable 60FPS तक पहुँचा दिया [0]
      [0] https://www.youtube.com/watch?v=t_rzYnXEQlE
    • मुझे वह दौर याद है जब rotation accuracy को 360/256 degrees की units तक सीमित करके एक byte में रखा जाता था, और उस value को trigonometric lookup table के index के रूप में इस्तेमाल करते थे :)
  • अगर आप LUTs के साथ बहुत काम करते हैं, तो मैं advanced color science और transformation work संभालने वाला एक Mac app बना रहा हूँ: https://videovillage.com/lattice

  • पहले मैंने NES homebrew scene में थोड़ा हाथ डाला था, और Bobl नाम के game में ऐसे कमाल के physics effects देखे जो system की calculation क्षमता से बहुत आगे लगते थे। बाद में पता चला कि वह lookup table था, और समझ आया कि simple tools से किसी चीज़ को बहुत complex process जैसा दिखाया जा सकता है
    https://morphcatgames.itch.io/bobl

    • यह मानने में कोई दिक्कत नहीं कि effect impressive है, लेकिन अगर आपका मतलब surface ripples या capillary waves से है, तो मुझे आश्चर्य है कि क्या 1D cellular automaton को real time में calculate करना NES के लिए सच में इतना मुश्किल होता
  • A Podcast Of Unnecessary Detail ने SNES Doom porting और trigonometric functions के लिए LUTs के इस्तेमाल पर एक episode किया था। context यह था कि SNES में graphics processor नहीं था
    https://festivalofthespokennerd.com/podcast/series-3-episode-4/
    https://github.com/RandalLinden/DOOM-FX

    • “SNES में graphics processor नहीं था” कहना पूरी तरह गलत है। NES में भी था। SNES के CPU, cloned Motorola 65c816, के अलावा PPU (picture processing unit) एक custom chip था जो CRT TV द्वारा हर scanline को physically draw किए जाने के समय tile-based backgrounds और sprites output करने के लिए कई layouts देता था
      यह background rotation और scaling भी कर सकता था। Mode 7 वही है—Mario Kart याद करें—और कई games में दिखने वाली hardware transparency भी support करता था। ऊपर से Doom और Starfox जैसे मामलों में cartridge में 3D calculations संभालने वाली Super FX chip लगी होती थी। इसलिए उस specific title में असल में दो graphics processors से काम लिया जा रहा था
      SNES hardware को शानदार और दर्दनाक रूप से detail में समझाने वाली Retro Game Mechanics Explained series है:
      https://www.youtube.com/watch?v=57ibhDU2SAI&list=PLHQ0utQyFw5KCcj1ljIhExH_lvGwfn6GV&index=1
  • मुझे याद आने वाले LUT के अपने uses ये थे: atmospheric scattering, sprites को color करना, night-vision scopes, FLIR scopes, black-and-white “video feed” effect, glitch effects, heightmap shading, spaceship exhaust plume के alpha dot coefficient, website visitors के mouse dwell heatmaps, crystalline effects, और अंत में raw color space में post-processing colorization
    LUT दरअसल पहले से ज्ञात values के array का visualization है, और हैरान करने वाली हद तक useful है

    • “sprites को color करना”—लगता है आजकल के बच्चे palette-based sprites सब भूल गए! “palette swap” शब्द आखिर आया कहाँ से होगा? ;)
      http://www.effectgames.com/demos/canvascycle/
      original Xbox यह ठीक से नहीं कर पाता था और Photoshop भी support नहीं करता था, इसलिए इसकी popularity घट गई। लेकिन modern hardware AESprite में बने palette swaps को आराम से handle कर सकता है