नोबल और मेडियन कट का उपयोग करके पिक्सेल नेबुला बनाना

मैं अपने खेल द लास्ट बाउंड्री में एक नेबुला चाहता था। वे अद्भुत दिखते हैं और अंतरिक्ष उनके बिना अंतरिक्ष नहीं है, लेकिन बस पृष्ठभूमि के आसपास बिखरे हुए सफेद पिक्सेल हैं। लेकिन जब से मैं गेम को "पिक्सेल आर्ट" की शैली में बनाता हूं, मुझे किसी तरह अपनी शोर लाइब्रेरी को पिक्लेटेड इमेज बनाने की जरूरत है।

यहाँ कुछ उदाहरण हैं:



और उदाहरण





एकल-रंग के उदाहरणों में, 8 रंगों का उपयोग किया जाता है, और अन्य में, 16 रंग। इस लेख में, मैं इस बारे में बात करूँगा कि मैंने द लास्ट बाउंड्री के लिए एक पिक्सेलयुक्त नेबुला कैसे बनाया।

जब हम एक शोर पुस्तकालय के साथ काम करते हैं, जैसे कि LibNoise , कोई फर्क नहीं पड़ता कि आप किस इंजन का उपयोग करते हैं (या अपना खुद का लिखते हैं), मूल्यों को आमतौर पर -1 से 1 तक की सीमा में वितरित किया जाता है। यह सैद्धांतिक रूप से अधिक संभावना है कि 2 डी शोर -0.7 से 0.7 की सीमा में होगा, लेकिन कुछ कार्यान्वयन परिणाम को स्केल करते हैं, इसे अंतराल में -1 से 1 तक अनुवाद करते हैं। 2 डी बनावट के साथ काम करने के लिए, इसे आमतौर पर 0 से 1 तक के अंतराल में परिवर्तित किया जाता है, और फिर यह RGB(0,0,0) से RGB(255,255,255) तक की सीमा में RGB(255,255,255)


x,y से उत्पन्न परलिन शोर x,y प्रत्येक पिक्सेल का x,y निर्देशांक 0.3f बढ़ाया जाता है

फिर आप छवि को बादलों की भव्यता का एहसास देने के लिए भिन्नात्मक ब्राउनियन गति का उपयोग कर सकते हैं।


पेरालिन शोर को 8 अष्टक, आवृत्ति 0.01 , नियमितता 0.5 और लक्सरिटी 2.0 साथ आंशिक ब्राउनियन गति के अधीन किया गया था।

मैंने देखा कि इंटरनेट पर पेरलिन शोर, सिंपल शोर, और आंशिक ब्राउनियन गति (fBm) के बहुत से गलत कार्यान्वयन हैं। लगता है कि क्या है, इसे लेकर बहुत भ्रम है। सुनिश्चित करें कि आप सही कार्यान्वयन का उपयोग करते हैं, क्योंकि यदि आप ऊपर वर्णित श्रृंखला बनाना चाहते हैं, तो गलत कार्यान्वयन के मामले में आपको आवश्यक परिणाम नहीं मिल सकते हैं।

आइए कल्पना करें कि हम एक धुआं प्रभाव बनाना चाहते हैं, अर्थात ऐसा समाधान हमारे लिए उपयुक्त होगा। लेकिन हमारा पिक्सेल आर्ट गेम अजीब लगेगा अगर इसमें नए रंगों का एक पूरा गुच्छा RGB(0,0,0) से RGB(255,255,255) तक दिखाई दिया। अचानक, खेल में ग्रे के 255 नए ग्रेड दिखाई देंगे।

हमें उन्हें सीमित संख्या में रंगों में बदलने की आवश्यकता है। वही हम बाद में करेंगे। इस बीच ...

यादृच्छिक नेबुला उत्पन्न करें


मैंने यादृच्छिक नीहारिका उत्पन्न करने के लिए तैयार ट्यूटोरियल के लिए दोहराया, लेकिन मेरे कुछ चरणों को जोड़ा और अपने स्वयं के शोर पुस्तकालय को लागू किया। मैंने इसे कुछ साल पहले लिखा था क्योंकि मैं पेर्लिन के शोर की अच्छी समझ प्राप्त करना चाहता था और आप इसका उपयोग अन्य अवधारणाओं के साथ बनावट और समान बनाने के लिए कैसे कर सकते हैं।

शायद आप मेरे कदम से कदम के बाद दोहरा सकते हैं या आपको उस कोड को जोड़ देना होगा जो आपके शोर को प्रभावित करेगा। मैं शुरुआती शोर पीढ़ी और fBm को छोड़कर सब कुछ समझाऊंगा ताकि आप खुद कोड लिख सकें; मुझे लगता है कि यह माना जा सकता है कि आपके पास पहले से ही शोर और fBm उत्पन्न करने की क्षमता है।

शुरू करने के लिए, मैं नेबुला उत्पन्न करने का परिणाम दिखाऊंगा:


समाप्त परिणाम

यह ध्यान रखना महत्वपूर्ण है कि यह अभी तक पिक्सेलित नहीं है। इसमें पिक्सेलेटेड तारों वाले आकाश के साथ रंगों की एक पूरी श्रृंखला है। नेबुला हम बाद में पिक्सेल करेंगे।

लाल, हरा, नीला, अल्फा और मास्क: पहली बात यह है कि पांच अलग-अलग बनावट उत्पन्न करते हैं। लाल, हरे और नीले रंग की बनावट के लिए अंतिम रंगीन चैनलों की जरूरत होती है। वास्तव में, मैं केवल एक या दो रंग चैनल उत्पन्न करता हूं, क्योंकि यह पता चला है कि तीनों का उपयोग करने से एक अविश्वसनीय रूप से रंगीन नेबुला पैदा होता है जो बदसूरत दिखता है। कोई एक रंग या दो रंगों का संयोजन अच्छा करेगा।

अल्फा चैनल महत्वपूर्ण है क्योंकि यह इस पर निर्भर करता है कि क्या नीच तारे नेबुला से चमकेंगे। मैं ऊपर दिखाए गए उदाहरण के अल्फा चैनल को प्रदर्शित करके इसका वर्णन करूंगा।


हमारे उदाहरण से तैयार अल्फा चैनल

इस क्षेत्र को whiter, 1.0 के करीब मान है, जो हमें 255 का अल्फा मान देता है। यह क्षेत्र जितना काला होगा, उतना ही पारदर्शी होगा। यदि आप एक उदाहरण देखते हैं, तो आप देख सकते हैं कि काले क्षेत्र उन क्षेत्रों के अनुरूप हैं जिनमें तारों वाला आकाश दिखाई देता है।


तारों वाला आकाश उदाहरण

ये उदाहरण के रूप में एक ही सितारे नहीं हैं, क्योंकि वे प्रत्येक स्क्रीनशॉट में बेतरतीब ढंग से उत्पन्न होते हैं। मुझे उम्मीद है कि यह आपको यह समझने से नहीं रोकता है कि निहारिका कैसे उत्पन्न होती है।

मेरे शोर पुस्तकालय में मॉड्यूल शामिल हैं, लिब शोर के उदाहरण के बाद। इस पुस्तकालय में सब कुछ "मॉड्यूल" है जिसे एक साथ जंजीर में डाला जा सकता है। कुछ मॉड्यूल नए मान (पेरलिन मॉड्यूल, लगातार मूल्य) उत्पन्न करते हैं, अन्य उन्हें कनेक्ट करते हैं (गुणा, जोड़ें), और कुछ बस मूल्य (Lerp, Clamp) पर संचालन करते हैं।

रंग चैनल


इससे कोई फर्क नहीं पड़ता कि हम एक, दो या तीन रंगों के साथ काम करते हैं - रेड, ग्रीन और ब्लू चैनल एक ही तरह से उत्पन्न होते हैं; मैं सिर्फ उनके लिए एक अलग बीज मूल्य का उपयोग करता हूं। मेरे बीज मान वर्तमान प्रणाली समय पर निर्भर करते हैं।

नीचे उन्हें सभी ग्रेस्केल में प्रस्तुत किया गया है, लेकिन सैद्धांतिक रूप से वे तीन चैनलों में से एक के लिए मूल्य हैं। ग्रेस्केल यहां केवल परिणामों को चित्रित करने के लिए है।

1. पेर्लिन का शोर


ऊपर के रूप में, पेर्लिन का शोर शुरुआती बिंदु होगा। यदि आप चाहें, तो आप सिम्पलेक्स शोर का उपयोग कर सकते हैं, ऐसा लगता है कि इसका 2 डी कार्यान्वयन केन पेरलिन से संबंधित नहीं है, लेकिन मैं गलत हो सकता है। गणितीय दृष्टिकोण से, सिंप्लेक्स शोर कम निर्देशों का उपयोग करता है, इसलिए एक समान नेबुला की पीढ़ी तेज होगी। चूंकि यह ग्रिड के बजाय सिम्प्लेक्स का उपयोग करता है, इसलिए यह थोड़ा अधिक सुंदर शोर पैदा करता है, लेकिन हम इसके साथ ज्यादा काम नहीं करेंगे, इसलिए यह विशेष रूप से महत्वपूर्ण नहीं है।

वास्तविक कोड नीचे नहीं दिखाया गया है, क्योंकि वास्तविक स्रोतों में x,y मानों को चरण 3 में fBm द्वारा बदल दिया गया था। यह सिर्फ x,y छवि का x,y निर्देशांक, स्थैतिक स्केलिंग कारक द्वारा गुणा किया गया है।


x,y से उत्पन्न परलिन शोर x,y प्रत्येक पिक्सेल का x,y निर्देशांक 0.3f बढ़ाया जाता है। यानी PixelValue = PerlinNoise(x * 0.3f, y * 0.3f)

पेरलिन शोर द्वारा बनाए गए मान लगभग -1 से 1 , इसलिए ऊपर दिखाए गए सामान्य ग्रेस्केल छवि बनाने के लिए, हम उन्हें 0 से 1 के अंतराल में परिवर्तित करते हैं। मैंने मानों के दायरे का परीक्षण किया ताकि रूपांतरण सबसे बड़ा विपरीत पैदा करे (सबसे कम मूल्य 0 , सबसे बड़ा - 1 मेल खाता है)।

2. गुणन


अगले मॉड्यूल ने उत्पन्न शोर को 5 गुणा किया। इसे कंट्रास्ट का समायोजन माना जा सकता है। नकारात्मक मूल्य गहरे हैं, सकारात्मक मूल्य हल्के हैं।

मेरे पास यहां दिखाने के लिए कुछ भी नहीं है, क्योंकि -5 से 5 के अंतराल से मान को 0 से 1 तक के अंतराल में परिवर्तित करने की प्रक्रिया में 1 परिणाम नहीं बदलता है।

3. आंशिक ब्राउनियन गति (fBM)


यह चरण शोर को बदल देता है जिसे कई लोग वास्तविक "शोर प्रभाव" मानते हैं। यहां हम perlin(x,y) को जोड़ने के लिए शोर फ़ंक्शन (हमारे मामले में, फ़ंक्शन perlin(x,y) ) से तेजी से छोटे नमूनों के ऑक्टेव को निष्पादित करते हैं।


ऊपर दिखाए गए पेर्लिन शोर का आंशिक ब्राउनियन गति। 8 सप्तक, आवृत्ति .01f , नियमितता .5f और 2.5f

आप पहले से ही कुछ दिलचस्प की उत्पत्ति देख सकते हैं। ऊपर दिखाई गई छवि x,y को पिक्सल्स के निर्देशांक x,y स्केलिंग से उत्पन्न नहीं होती है, fBM ऐसा करती है। फिर से, इन मानों को 0 से 1 अंतराल पर -5 से 5 तक के संभावित अंतराल में -5 जाता है।

4. प्रतिबंध (दबाना)


अब मैं मानों को -1 से 1 सीमा तक सीमित कर दूंगा। इस अंतराल के बाहर कुछ भी पूरी तरह से खारिज कर दिया जाएगा।


वही fBm, जो -1 से 1 तक सीमित है

इस ऑपरेशन का कार्य तेज ढाल बनाने और पूर्ण सफेद या काले रंग में क्षेत्र को बढ़ाते हुए मूल्यों को एक छोटे अंतराल में परिवर्तित करना है। ये मृत या खाली क्षेत्र नेबुला प्रभाव के लिए महत्वपूर्ण हैं, जिसे हम बाद में संबोधित करेंगे। यदि हमने पहले 5 से गुणा नहीं किया होता, तो क्लैंप कुछ भी नहीं बदलता।

5. जोड़ें


अब हम क्लैंप से मान लेते हैं और 1. उन्हें जोड़ते हैं। इस प्रकार, हम मान को 0 से 2 तक अंतराल में स्थानांतरित करते हैं। रूपांतरण के बाद, परिणाम पहले जैसे ही दिखेंगे।

6. 2 से भाग दें


आप शायद जानते हैं कि जब मैं परिणाम को 2 विभाजित करूंगा (तब तक गुणा करें। .5 )। छवि में, फिर से कुछ भी नहीं बदलेगा।

चरण 5 और 6 मानों को 0 से 1 तक की श्रेणी में परिवर्तित करते हैं।

7. एक विरूपण बनावट बनाएँ


अगला कदम विरूपण बनावट बनाने के लिए है। मैं इसे पर्लिन शोर (नए बीज मूल्य के साथ)> 4 से गुणा करके fBm निष्पादित करूंगा। इस मामले में, एफबीएम 5 ऑक्टेव्स का उपयोग करता है, 0.025 आवृत्ति, 0.5 की एक नियमितता और 1.5 की एक ल्युनैरिटी।


विरूपण बनावट

नेबुला की मौजूदा बनावट की तुलना में अधिक विवरण बनाने के लिए इस बनावट की आवश्यकता है। निहारिका एक बड़ा लहराती बादल है, और यह बनावट इसमें छोटे बदलाव करेगी। इसके माध्यम से, पेरलिन के शोर की ग्रिड प्रकृति उभरने लगेगी।

8. ऑफसेट बनावट का उपयोग करके रंग की बनावट को बंद करें


आगे मैं इन दो बनावटों को ले जाऊंगा और एक कारक द्वारा दूसरे के निर्देशांक को ऑफसेट करने के लिए उपयोग करूंगा। हमारे मामले में, संयोजन इस तरह दिखता है:


बायस परिणाम

विरूपण बनावट का उपयोग x,y निर्देशांक को बदलने के लिए किया जाता है जिसे हम स्रोत शोर डेटा में देख रहे हैं।

याद रखें कि ऊपर दिखाई गई छवियां केवल चित्रण प्रयोजनों के लिए हैं। प्रत्येक चरण में, हमारे पास वास्तव में केवल एक शोर समारोह होता है। हम इसे मान x,y , और यह एक नंबर लौटाता है। कुछ चरणों में, इस संख्या का अंतराल अलग हो सकता है, लेकिन ऊपर हमने एक छवि बनाने के लिए इसे वापस ग्रेस्केल में बदल दिया। छवि प्रत्येक x,y का उपयोग करके बनाई गई है छवि का x,y समन्वय, शोर फ़ंक्शन द्वारा प्रेषित।

जब हम कहते हैं:

मुझे एक्स = 0 और वाई = 0 के साथ ऊपरी बाएं कोने के पिक्सेल के लिए मूल्य दें

फ़ंक्शन हमें एक नंबर देता है। यदि हम इसके लिए पेरलिन से पूछते हैं, तो हम जानते हैं कि यह -1 और 1 बीच होगा, यदि, जैसा कि ऊपर, हम क्लैंप लागू करते हैं, जोड़ और गुणा करते हैं, हमें 0 और 1 बीच एक मान मिलता है।

इसे समझने के बाद, हम सीखते हैं कि विरूपण शोर फ़ंक्शन -1 से 1 तक की सीमा में मान बनाता है। इसलिए, जब हम कहते हैं कि पूर्वाग्रह करना है:

मुझे पिक्सेल X = 0 और Y = 0 के साथ ऊपरी बाएँ कोने में पिक्सेल के लिए मान दें

ऑफसेट मॉड्यूल पहले x,y निर्देशांक के लिए ऑफसेट फ़ंक्शन को पूछता है। इसका परिणाम -1 और 1 बीच है (जैसा कि ऊपर था)। फिर इसे 40 से गुणा किया जाता है (यह मेरे द्वारा चयनित गुणांक है )। परिणाम -40 और 40 बीच का मान होगा।

फिर हम इस मान को लेते हैं और इसे निर्देशांक में x,y जोड़ते हैं x,y जिसे हम खोज रहे थे, और इस परिणाम का उपयोग रंग बनावट खोजने के लिए करते हैं। हम क्लैंप के साथ नकारात्मक मानों को 0 से काटते हैं, क्योंकि नकारात्मक x,y तलाश करना असंभव है x,y शोर कार्यों में x,y निर्देशांक (कम से कम मेरे शोर पुस्तकालय में)।

अर्थात्, सामान्य रूप से, यह इस तरह दिखता है:

 ColourFunction(x,y) =     0  1 DisplaceFunction(x,y) =     -1  1 DoDisplace(x,y) = { v = DisplaceFunction(x,y) * factor clamp(v,0,40) x = x + v; y = y + v; if x < 0 then x = 0 if y < 0 then y = 0 return ColourFunction(x,y) } 

मुझे आशा है कि आप इसे समझेंगे। वास्तव में, हम उस x,y को नहीं देख रहे हैं जो हम में थे, लेकिन ऑफसेट पर। और चूंकि परिमाण भी एक सहज ढाल है, इसलिए यह आसानी से बदल जाता है।

ऑफसेट करने के अन्य तरीके हैं। मेरे शोर पुस्तकालय में एक मॉड्यूल है जो एक सर्पिल विस्थापन बनाता है। इसका उपयोग बनावट को आकर्षित करने के लिए किया जा सकता है, धीरे-धीरे घटकर कई बिंदुओं तक पहुंच सकता है। यहाँ एक उदाहरण है

वह सब है। हम प्रत्येक रंग चैनल के लिए नए बीज मानों का उपयोग करते हुए, उपरोक्त ऑपरेशनों को तीन बार दोहराते हैं। आप एक या दो चैनल बना सकते हैं। मुझे नहीं लगता कि यह तीसरा बनाने लायक है।

अल्फा चैनल


एक अल्फा चैनल को उसी तरह बनाया जाता है जैसे कलर चैनल:

  1. हम पेरलिन के शोर के साथ शुरू करते हैं
  2. 5 गुणा करें
  3. 8 ओक्टेव्स के साथ एफबीएम, फ्रिक्वेंसी 0.005 , रेग्युलरिटी 0.5 और लक्सरिटी 2.5
  4. हम क्लैंप का उपयोग करके अंतराल को -1 से 1 तक सीमित करते हैं, 1 को जोड़ते हैं, 2 विभाजित करते हैं (यानी, हम अंतराल को -1 से 1 तक अंतराल को 0 से 1 तक शिफ्ट करते हैं।
  5. हम नकारात्मक दिशा में एक छोटी राशि द्वारा परिणाम को स्थानांतरित करते हैं। मैं 0.4 ऑफसेट। इसके लिए धन्यवाद, सब कुछ थोड़ा गहरा हो जाता है।
  6. हम परिणामों को 0 से 1 अंतराल तक सीमित करते हैं। चूंकि हमने सब कुछ स्थानांतरित किया, जिससे यह थोड़ा गहरा हो गया, वास्तव में, हमने 0 साथ अधिक क्षेत्र बनाए, और कुछ क्षेत्र नकारात्मक मूल्यों में चले गए।

परिणाम एक अल्फा चैनल बनावट है।


अल्फा बनावट

जैसा कि मैंने कहा, काले क्षेत्र पारदर्शी होंगे, और सफेद क्षेत्र अपारदर्शी होंगे।

चैनल मास्क


यह अंतिम बनावट है जो सब कुछ के ऊपर छाया हुआ छाया बनाने के लिए उपयोग की जाती है। यह अन्य सभी बनावटों की तरह ही शुरू होता है:

  1. शोरगुल
  2. 5 गुणा करें
  3. हम fBm, 5 ऑक्टेव्स, फ्रीक्वेंसी 0.01 , रेग्युलरिटी 0.1 , लैकुनारिटी 0.1 परफॉर्म करते हैं। नियमितता छोटी है, इसलिए बादल कम घना है
  4. -1 से 1 तक के अंतराल को -1 से 1 के अंतराल अंतराल पर करें

लेकिन हम ऐसे दो पाठ बनाते हैं:


मास्क ए


मास्क बी

हम इन दो बनावटों को उजागर करते हैं जिन्हें मैं चयन मॉड्यूल कहता हूं। वास्तव में, हम मॉड्यूल ए या मॉड्यूल बी से मूल्य का उपयोग करते हैं। विकल्प मॉड्यूल सी के मूल्य पर निर्भर करता है। इसके लिए दो और मानों की आवश्यकता होती है - प्वाइंट और फॉलऑफ का चयन करें

अगर पॉइंट x,y का मान x,y मॉड्यूल C का x,y SelectPoint से अधिक या बराबर है, तो हम मॉड्यूल B के मान का उपयोग करते हैं x,y मॉड्यूल B का मान। अगर SelectPoint - Falloff के मान से कम या बराबर है, तो हम x,y मॉड्यूल A के मान का उपयोग करते हैं।

यदि यह SelectPoint - Falloff और SelectPoint बीच है, तो हम मॉड्यूल A और मॉड्यूल B के x,y मानों के बीच रैखिक प्रक्षेप करते हैं।

 float select(x, y, moduleA, moduleB, moduleC, selectPoint, falloff) { float s = moduleC(x,y); if(s >= selectPoint) return moduleB(x,y); else if(s <= selectPoint - falloff) return moduleA(x,y); else { float a = moduleA(x,y); float b = moduleB(x,y); return lerp(a, b, (1.0 / ((selectPoint - (selectPoint-falloff)) / (selectPoint - s))); } } 

हमारे मामले में, मॉड्यूल ए 0 मान के साथ एक निरंतर मॉड्यूल है। मॉड्यूल बी मुखौटा ए की पहली बनावट है, और चयनकर्ता (मॉड्यूल सी) बी का दूसरा मुखौटा है। SelectPoint 0.4 होगा, और SelectPoint 0.1 होगा। नतीजतन, हम प्राप्त करते हैं:


अंतिम मुखौटा

SelectPoint बढ़ाने या घटाने से, हम मुखौटा में काले रंग की मात्रा घटाते या बढ़ाते हैं। falloff में वृद्धि या कमी करके, हम मुखौटे के नरम किनारों को बढ़ाते हैं या घटाते हैं। मास्क में से एक के बजाय, मैं 1 मूल्य के साथ लगातार मॉड्यूल का उपयोग कर सकता था, लेकिन मैं "बेपर्दा" क्षेत्रों में थोड़ा यादृच्छिकता जोड़ना चाहता था।

कलर चैनल और मास्क मिलाएं


अब हमें प्रत्येक रंगीन चैनलों पर मास्क लगाने की आवश्यकता है। यह ब्लेंडिंग मॉड्यूल का उपयोग करके किया जाता है। यह दो मॉड्यूल से मूल्यों के प्रतिशत को जोड़ता है ताकि मानों का योग 100% हो।

यही है, हम x,y के मान का 50% x,y मॉड्यूल A के x,y और x,y के मान का 50% x,y मॉड्यूल B के x,y या 75% और 25%, आदि ले सकते हैं। प्रत्येक मॉड्यूल से जो प्रतिशत हम लेते हैं वह दूसरे मॉड्यूल - मॉड्यूल सी पर निर्भर करता है। यदि मॉड्यूल C का x,y में मान 0 , तो हम मॉड्यूल A से 100% और मॉड्यूल B से 0% लेंगे। यदि यह 1 , तो हम लेते हैं उलटा मान।

प्रत्येक रंग की बनावट के लिए मिश्रण।

  • मॉड्यूल ए - लगातार मान 0
  • मॉड्यूल बी रंग चैनल है जिसे हमने पहले ही देखा है
  • मॉड्यूल सी - मुखौटा परिणाम

इसका मतलब यह है कि रंगीन चैनल का शोर केवल उसी स्थान पर प्रदर्शित किया जाएगा जहां मुखौटा में 0 (सफेद के करीब क्षेत्रों) के ऊपर मान हैं, और उनकी दृश्यता का परिमाण मुखौटा के मूल्य पर निर्भर करता है।

यहाँ हमारे उदाहरण के लिए परिणाम है:


अंतिम परिणाम

एक मुखौटा के साथ सम्मिश्रण लागू करने से पहले मूल से इसकी तुलना करें।


मास्क के साथ मिश्रण करने से पहले

शायद यह उदाहरण बहुत स्पष्ट नहीं है, लेकिन मौका के कारण विशेष रूप से एक अच्छा उदाहरण चुनना मुश्किल है। मास्क का प्रभाव गहरे क्षेत्रों को बनाने के लिए है। बेशक, आप मुखौटा को अनुकूलित कर सकते हैं ताकि वे अधिक स्पष्ट हों।

यहां यह महत्वपूर्ण है कि पूरे रंग चैनल पर एक ही मुखौटा लागू किया जाता है, अर्थात, समान क्षेत्र छाया में दिखाई देते हैं।

हम सब कुछ एक साथ जोड़ते हैं


हमारे प्रारंभिक समाप्त उदाहरण:


तैयार उदाहरण

यह लाल, हरा और अल्फा चैनल का उपयोग करता है:


लाल चैनल


ग्रीन चैनल


अल्फा चैनल

और फिर हम बस उन्हें अपने तारों वाले आकाश के ऊपर बिछाते हैं।

अब सब कुछ बहुत अच्छा लग रहा है, लेकिन पिक्सेल आर्ट गेम के लिए बहुत उपयुक्त नहीं है। हमें रंगों की संख्या कम करने की आवश्यकता है ...

मेडियन कट


लेख के इस भाग को किसी भी चीज़ पर लागू किया जा सकता है। मान लें कि आप एक संगमरमर की बनावट उत्पन्न करते हैं और रंगों की संख्या कम करना चाहते हैं। यह वह जगह है जहाँ माध्य कट एल्गोरिथ्म काम में आता है। हम इसका उपयोग ऊपर दिखाए गए नेबुला में रंगों की संख्या को कम करने के लिए करेंगे।

यह तब होता है, जब यह तारों से भरे आसमान पर चढ़ जाता है। रंगों की संख्या पूरी तरह से मनमाना है।

मेडियन कट एल्गोरिदम जैसा कि विकिपीडिया में वर्णित है:

मान लें कि हमारे पास पिक्सेल की एक मनमानी संख्या के साथ एक छवि है और हम 16 रंगों का एक पैलेट उत्पन्न करना चाहते हैं। सभी पिक्सेल को छवि में (जैसे उनके RGB मान ) ट्रैश में रखें । पता लगाएं कि टोकरी में सभी पिक्सेल के बीच कौन सा रंग चैनल (लाल, हरा या नीला) है, इसमें सबसे बड़ी श्रेणी के मान हैं, और फिर इस चैनल के मूल्यों के अनुसार पिक्सेल को सॉर्ट करें। उदाहरण के लिए, यदि नीले चैनल में मानों की सबसे बड़ी श्रृंखला है, तो RGB मान (32, 8, 16) वाले पिक्सेल RGB मान (1, 2, 24) वाले पिक्सेल से छोटा होता है, क्योंकि 16 <24। टोकरी को सॉर्ट करने के बाद, पिक्सेल के ऊपरी आधे भाग को रखें। एक नई टोकरी में। (इस चरण ने माध्यिका कट एल्गोरिथ्म को नाम दिया; पिक्सेल्स की सूची के माध्यिका से बास्केट को आधे में विभाजित किया गया है।) दोनों बास्केट के लिए प्रक्रिया को दोहराएं, जो हमें 4 बास्केट देगी, फिर सभी 4 बास्केट के लिए दोहराएगी, 8 बास्केट प्राप्त करेगी, फिर 8 बास्केट के लिए दोहराएगी, हमें 16 मिलेंगे। बास्केट। हम प्रत्येक टोकरियों में पिक्सेल को औसत करते हैं और 16 रंगों का एक पैलेट प्राप्त करते हैं। चूंकि प्रत्येक पुनरावृत्ति पर बास्केट की संख्या दोगुनी हो जाती है, एल्गोरिथ्म केवल ऐसे पैलेट उत्पन्न कर सकता है, जिसमें रंगों की संख्या दो की शक्ति है । उदाहरण के लिए, 12-रंग की पैलेट बनाने के लिए, आपको पहले 16-रंग की पैलेट तैयार करनी होगी, और फिर किसी तरह कुछ रंगों को जोड़ना होगा।

स्रोत: https://en.wikipedia.org/wiki/Median_cut

यह स्पष्टीकरण मुझे बुरा लग रहा था और विशेष रूप से उपयोगी नहीं था। एल्गोरिथ्म को लागू करते समय, बल्कि बदसूरत छवियां इस तरह से प्राप्त की जाती हैं। मैंने इसे कुछ बदलावों के साथ लागू किया:

  1. हम अंतराल को दर्शाते हुए मूल्य के साथ boxes कंटेनर को संग्रहीत करते हैं (नीचे इस पर अधिक)। box केवल मूल छवि से पिक्सेल की कुछ गतिशील संख्या संग्रहीत करता है।
  2. पहले रूप में मूल छवि से सभी पिक्सेल जोड़ें और अंतराल 0 उपयोग करें
  3. जबकि की कुल संख्या आवश्यक रंगों से कम है, हम निम्नलिखित चरणों को जारी रखते हैं।
  4. यदि अंतराल मान 0 , तो प्रत्येक वर्तमान बॉक्स के लिए हम इस box के मुख्य रंग चैनल को निर्धारित करते हैं, और फिर इस रंग द्वारा इस box में पिक्सेल को सॉर्ट करते हैं। — Red, Green, Blue Alpha, . , redRange = Max(Red) - Min(Red) . , .
  5. box boxes . , box .
  6. , 4 5 box , boxes . , , , . , , .
  7. box ( == ) boxes . 0 ( ). , , , — . .

जब हम वांछित रंगों के बराबर बक्से की संख्या तक पहुंचते हैं, तो हम पैलेट तत्व को निर्धारित करने के लिए प्रत्येक बॉक्स में सभी पिक्सल को औसत करते हैं जो इन रंगों को सबसे अच्छा सूट करता है। मैंने अभी यूक्लिडियन दूरी का उपयोग किया है, लेकिन अवधारणात्मक समाधान हैं जो इसे बेहतर कर सकते हैं।

यहां एक ऐसी छवि है जो सब कुछ अधिक स्पष्ट रूप से समझाएगी। प्रदर्शन के लिए, मैं केवल RGB का उपयोग करता हूं, क्योंकि अल्फा दिखाना मुश्किल है।


आइए इस विधि को हमारी उदाहरण छवि पर लागू करें।


मूल


मीडियन कट 16 रंगों तक

मुझे पता चला कि दो रंग चैनलों का उपयोग करते समय, 16 रंगों के साथ एक अच्छा प्रभाव प्राप्त होता है। लेकिन ध्यान रखें कि यहां हम अल्फा चैनल का उपयोग करते हैं, जो रंगों के बीच की दूरी की गणना में भी शामिल है। इसलिए यदि आप पारदर्शिता की परवाह नहीं करते हैं, तो आप कम रंगों का उपयोग कर सकते हैं। चूंकि मेरा माध्यिका कट, विकिपीडिया उदाहरण के विपरीत, रंगों की एक मनमानी संख्या (और केवल दो डिग्री नहीं) का उपयोग कर सकता है, तो आप इसे अपनी आवश्यकताओं के अनुसार अनुकूलित कर सकते हैं।


16 से 2 रंगों से।

हमने प्रत्येक से एक रंग का चयन किया box, बस सभी मूल्यों को औसत किया। हालांकि, यह एकमात्र तरीका नहीं है। आपने देखा होगा कि मूल की तुलना में हमारा परिणाम इतना उज्ज्वल नहीं है। यदि आपको इसकी आवश्यकता है, तो आप ऊपरी अंतराल में वरीयता दे सकते हैं, अंतराल की परिभाषा में वजन जोड़ सकते हैं। या आप आसानी से छवि में चमकीले रंगों के 1, 2 या 3 का चयन कर सकते हैं और उन्हें पैलेट में जोड़ सकते हैं। इसलिए, यदि आपको 16 रंगों की आवश्यकता है, तो 13 रंगों का एक पैलेट बनाएं और मैन्युअल रूप से अपने उज्ज्वल रंगों को जोड़ें।


तीन सबसे चमकीले रंगों के साथ एक पैलेट

अब सब कुछ बहुत अच्छा लग रहा है, लेकिन तस्वीर बहुत ही चमकदार है। इसमें एक ही रंग के बड़े क्षेत्र हैं। अब हमें उन्हें सुचारू करने की आवश्यकता है।

तड़पना


मुझे आपको यह बताने की आवश्यकता नहीं है कि क्या कम है, क्योंकि आप पहले से ही पिक्सेल कला के साथ काम करते हैं। इसलिए, एक चिकनी तस्वीर प्राप्त करने के लिए, हम एक डीथरिंग एल्गोरिदम का उपयोग करेंगे, जिनमें से बहुत सारे हैं।

मैंने एक साधारण फ्लोयड-स्टाइनबर्ग डीथिरिंग एल्गोरिदम लागू किया कोई अप्रिय आश्चर्य नहीं हुआ। हालांकि, प्रभाव काफी मजबूत था। यहाँ फिर से हमारा उदाहरण है:


मूल

फिर हमने पैलेट को 16 रंगों में काट दिया:


मानों को 16-रंग के पैलेट में मैप किया जाता है।

और अब पैलेट द्वारा रूपांतरण के बाद dithering किया जाता है:


समाप्त करने के साथ परिणाम

Source: https://habr.com/ru/post/hi464203/


All Articles