एक बनावट एटलस में बनावट के रक्तस्राव से कैसे बचें?


46

मेरे खेल में क्यूब्स से बना एक Minecraft जैसा इलाका है। मैं वॉक्सेल डेटा से एक वर्टेक्स बफर उत्पन्न करता हूं और विभिन्न ब्लॉकों के लुक के लिए टेक्सचर एटलस का उपयोग करता हूं:

स्वर आधारित क्षेत्र के लिए बनावट एटलस

समस्या यह है कि दूर के क्यूब्स की बनावट बनावट एटलस में आसन्न टाइलों के साथ प्रक्षेपित होती है। क्यूब्स के बीच गलत रंगों की रेखाओं के परिणामस्वरूप (चित्रमय दोषों को देखने के लिए आपको इसके पूर्ण आकार से नीचे स्क्रीनशॉट देखने की आवश्यकता हो सकती है):

गलत रंग की धारियों के साथ इलाके का स्क्रीनशॉट

अभी के लिए मैं इन प्रक्षेप सेटिंग्स का उपयोग करता हूं, लेकिन मैंने हर संयोजन की कोशिश की और यहां तक ​​कि GL_NEARESTबिना मानचित्रण के बेहतर परिणाम प्रदान नहीं करता है।

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

मैंने टाइल के थोड़े छोटे क्षेत्र को चुनने के लिए बनावट के निर्देशांक में एक ऑफसेट जोड़ने की कोशिश की, लेकिन चूंकि अवांछित प्रभाव कैमरे की दूरी पर निर्भर करता है, इसलिए यह समस्या को पूरी तरह से हल नहीं कर सकता है। कुछ ही दूरी पर धारियां होती हैं।

मैं इस बनावट के रक्तस्राव को कैसे हल कर सकता हूं? एक बनावट एटलस का उपयोग करने के बाद से यह एक आम दृष्टिकोण हो सकता है लोकप्रिय तकनीक है। अफसोस की बात है, कुछ कारणों से टिप्पणियों में समझाया गया है, मैं अलग-अलग बनावट या बनावट सरणियों में नहीं बदल सकता।


4
समस्या मानचित्रण के साथ है - आपकी बनावट निर्देशांक सबसे बड़े मील स्तर के लिए अच्छी तरह से काम कर सकती है, लेकिन जैसे-जैसे चीजें आगे बढ़ती हैं, सीमा टाइल एक साथ मिलती हैं। आप अपने गार्ड ज़ोन (टाइल्स के बीच का क्षेत्र) को बढ़ाते हुए, mipmaps (शायद एक अच्छा विचार नहीं है) का उपयोग करके यह लड़ाई लड़ सकते हैं, mip स्तर (मुश्किल) के आधार पर shader में गार्ड ज़ोन को गतिशील रूप से बढ़ाते हुए, कुछ अजीब करते हैं, जो bipmaps उत्पन्न कर सकते हैं (कर सकते हैं) 'हालांकि कुछ भी सोचें) .. मैंने इस समस्या से खुद को कभी नहीं निपटाया है, लेकिन इसके साथ शुरू करने के लिए सामान है .. =)
जरी कोम्पा

जैसा कि मैंने कहा कि दुख की बात है कि मैपिंग को बंद करने से समस्या हल नहीं होती है। Mipmaps के बिना यह या तो रैखिक को प्रक्षेपित करेगा GL_LINEARजो एक समान परिणाम देता है या निकटतम पिक्सेल उठाता है GL_NEARESTजो किसी भी तरह ब्लॉकों के बीच धारियों में परिणाम करता है। अंतिम उल्लिखित विकल्प कम हो जाता है लेकिन पिक्सेल दोष को समाप्त नहीं करता है।
दानीझार '

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

1
मुझे पहले यह समस्या थी और प्रत्येक अलग बनावट के बीच आपके एटलस में 1-2 पिक्सेल पैडिंग जोड़कर इसे हल किया गया था।
चक डी

1
@Kylotan। समस्या बनावट के आकार के बारे में है अगर यह mipmaps, रैखिक प्रक्षेप या निकटतम पिक्सेल उठा द्वारा किया जाता है।
दानियार

जवाबों:


34

ठीक है, मुझे लगता है कि आपको यहां दो समस्याएं चल रही हैं।

पहली समस्या mipmapping के साथ है। सामान्य तौर पर, आप मैपमैपिंग के साथ एटलसिंग को भोलेपन से नहीं करना चाहते हैं, क्योंकि जब तक आपके सभी सबटेक्स्ट बिल्कुल 1x1 पिक्सेल आकार के नहीं होंगे, तब तक आपको बनावट रक्तस्राव का अनुभव होगा। पैडिंग को जोड़ने से समस्या को निचले स्तर तक ले जाया जाएगा।

अंगूठे के एक नियम के रूप में, 2 डी के लिए, जो कि आप आमतौर पर एटलसिंग करते हैं, आप मिपमप नहीं करते हैं; 3 डी के लिए, जो कि आप माइपमैप हैं, आप एटलस नहीं करते हैं (वास्तव में, आप इस तरह से त्वचा बनाते हैं कि रक्तस्राव एक समस्या नहीं होगी)

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

मान लीजिए कि एक 8x8 बनावट है। संभवतः (0,0) से (0.5, 0.5) के uv निर्देशांक का उपयोग करके आप शीर्ष-बाईं तिमाही प्राप्त कर रहे हैं:

गलत मैपिंग

और समस्या यह है कि यू-समन्वित 0.5 पर, नमूना बाएं गंतव्य के आधे और दाएं टेक्सल के आधे हिस्से का उपयोग करके गंतव्य के टुकड़े को प्रक्षेपित करेगा। वही u-निर्देशांक 0 पर होगा, और v-निर्देशांक के लिए भी यही होगा। ऐसा इसलिए है क्योंकि आप टेक्सल्स के बीच सीमाओं को संबोधित कर रहे हैं, न कि केंद्रों को।

इसके बजाय आपको क्या करना चाहिए, यह प्रत्येक टेक्सल का केंद्र है। इस उदाहरण में, ये वे निर्देशांक हैं जिनका आप उपयोग करना चाहते हैं:

सही मैपिंग

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

सामान्यीकृत करने के लिए, यदि आप एक विशिष्ट टेक्सल का उपयोग करना चाहते हैं, तो निर्देशांक की गणना इस प्रकार की जाती है:

function get_texel_coords(x, y, tex_width, tex_height)
    u = (x + 0.5) / tex_width
    v = (y + 0.5) / tex_height
    return u, v
end

इसे "आधा पिक्सेल सुधार" कहा जाता है। यदि आप रुचि रखते हैं, तो यहां अधिक विस्तृत विवरण दिया गया है


आपका स्पष्टीकरण बहुत आशाजनक लगता है। दुख की बात है कि इस समय मेरे पास वीडियो कार्ड है, मैं इसे अभी तक लागू नहीं कर सकता। अगर रिपेयर किया गया कार्ड आता है तो मैं ऐसा करूंगा। और मैं तब टाइलों की सीमाओं पर हस्तक्षेप किए बिना एटलस के mipmaps की गणना स्वयं करूंगा।
डानिजर

@ शेराथिस यदि आपको निश्चित रूप से एटलस करना है, तो सुनिश्चित करें कि आपके सबटेक्स्ट के आकार 2 की शक्तियों में हैं, इसलिए आप रक्तस्राव को न्यूनतम एमआईपी स्तर तक सीमित कर सकते हैं। यदि आप ऐसा करते हैं, तो आपको वास्तव में अपने खुद के mipmaps को शिल्प करने की आवश्यकता नहीं है।
पांडा पजामा

यहां तक ​​कि PoT के आकार के बनावट में भी कलाकृतियां हो सकती हैं, क्योंकि बिलिनियर फ़िल्टरिंग उन सीमाओं को पार कर सकती है। (कम से कम कार्यान्वयन में मैंने देखा है।) आधे पिक्सेल सुधार के लिए, क्या इस मामले में आवेदन करना चाहिए? यदि मैं उदाहरण के लिए उनकी रॉक बनावट को मैप करना चाहता था, तो निश्चित रूप से यू और वी निर्देशांक के साथ हमेशा 0.0 से 0.25 होगा?
काइलोटन

1
@ किलोटन यदि आपकी बनावट का आकार समान है, और सभी सबटेक्स्ट के आकार भी समान हैं और समतल दिशाओं में स्थित हैं, तो बनावट के आकार को कम करने पर बिलिनियर फ़िल्टरिंग सबटेक्स्चर के बीच मिश्रण नहीं करेगा। दो की शक्तियों के लिए सामान्यीकरण करें (यदि आप कलाकृतियों को देख रहे हैं, तो आप शायद बाइबिक का उपयोग कर रहे हैं, बिलिनियर फ़िल्टरिंग का नहीं)। आधे-पिक्सेल सुधार के बारे में, यह आवश्यक है, क्योंकि 0.25 सबसे सही टेक्सल नहीं है, लेकिन दोनों उप-वर्गों के बीच का मध्य बिंदु है। इसे परिप्रेक्ष्य में रखने के लिए, कल्पना करें कि आप रैस्टराइज़र हैं: (0.00, 0.25) पर बनावट का रंग क्या है?
पांडा पायजामा


19

एक विकल्प है कि mipmaps के साथ fiddling की तुलना में बहुत आसान हो जाएगा और बनावट समन्वय फ़ज़ल कारकों को जोड़ना एक बनावट सरणी का उपयोग करना है। बनावट सरणियाँ 3 डी बनावट के समान हैं, लेकिन 3 आयाम में कोई मैपिंग के साथ नहीं है, इसलिए वे बनावट एटलस के लिए आदर्श हैं जहां "सबटेक्स्टर्स" सभी समान आकार हैं।

http://www.opengl.org/wiki/Array_Texture


यदि वे उपलब्ध हैं, तो वे बहुत बेहतर समाधान हैं - आपको अन्य सुविधाएं भी मिलती हैं, जैसे कि रैपिंग टेक्सचर, जो कि आपको कम से कम याद आते हैं।
जरी कोमप्पा

@JariKomppa। मैं बनावट सरणियों का उपयोग नहीं करना चाहता, क्योंकि इस तरह से मैं इलाके के लिए अतिरिक्त शेड होगा। चूंकि मैं जो इंजन लिखता हूं वह सामान्य होना चाहिए क्योंकि मैं यह अपवाद नहीं बनाना चाहता। क्या एक ऐसा शेडर बनाने का कोई तरीका है जो बनावट बनावट और एकल बनावट दोनों को संभाल सके?
दानियार १०'१३ को २०:४

8
@sharethis असंदिग्ध रूप से सुपरियर तकनीकी समाधानों को खारिज करना क्योंकि आप "सामान्य" होना चाहते हैं, विफलता के लिए एक नुस्खा है। यदि आप एक खेल लिखते हैं, तो एक इंजन न लिखें।
सम होसेवार ११'१३

@SamHocevar। मैं एक इंजन लिख रहा हूं और मेरी परियोजना एक विशिष्ट वास्तुकला के बारे में है जो घटक पूरी तरह से विघटित थे। तो फार्म घटक को इलाके के घटक का ध्यान नहीं रखना चाहिए जो केवल मानक बफ़र्स और एक मानक बनावट प्रदान करना चाहिए।
दनिजर

1
@ शेराथिस ठीक है। मैं किसी भी तरह से "मेरे खेल में" सवाल का हिस्सा था।
सम होसेवार

6

इस मुद्दे पर बहुत संघर्ष करने के बाद, आखिरकार मैं एक समाधान लेकर आया।

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

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

इन मापदंडों के साथ, कोई रक्तस्राव नहीं होता है।

कस्टम mipmaps प्रदान करते समय आपको एक बात ध्यान देनी होगी। चूंकि यह एटलस को सिकोड़ने के लिए समझ में नहीं आता है, भले ही प्रत्येक टाइल पहले से ही हो 1x1, जो आप प्रदान करते हैं उसके अनुसार अधिकतम मिपमैप स्तर निर्धारित किया जाना चाहिए।

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); // pick mipmap level 7 or lower

अन्य सभी उत्तर और बहुत उपयोगी टिप्पणियों के लिए धन्यवाद! वैसे मैं अभी भी नहीं जानता कि रैखिक अप स्केलिंग का उपयोग कैसे करें, लेकिन मुझे लगता है कि कोई रास्ता नहीं है।


आपको यह जानकर अच्छा लगा। आपको इस उत्तर को मेरे बजाय सही के रूप में चिह्नित करना चाहिए।
पांडा पाजामा

mipmapping विशेष रूप से डाउनसम्पलिंग के लिए एक तकनीक है, जो अपसम्पलिंग के लिए कोई मतलब नहीं है। यह विचार है कि यदि आप एक छोटे त्रिभुज को बनाने जा रहे हैं, तो एक बड़ी बनावट का नमूना लेने में बहुत समय लगेगा, बस इसमें से कुछ पिक्सेल मिलेंगे, इसलिए आप इसे पूर्व-डाउन करें और उपयुक्त mip स्तर का उपयोग करें ड्राइंग छोटे त्रिकोण। बड़े त्रिकोणों के लिए, बड़े mip स्तर से अलग कुछ भी उपयोग करने का कोई मतलब नहीं है, इसलिए यह कुछ करने के लिए एक त्रुटि हैglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
पांडा Pajama

@PandaPajama। आप सही हैं, मैंने अपना जवाब सही किया। रक्तस्राव के कारण के लिए सेट GL_TEXTURE_MAX_FILTERकरने के लिए सेट करने के GL_NEAREST_MIPMAP_LINEARलिए नहीं, बल्कि प्रक्षेप के कारण। तो इस मामले में यह बराबर है GL_LINEARक्योंकि वैसे भी सबसे कम mipmap स्तर का उपयोग किया जाता है।
दानीजार

@danijar - क्या आप और अधिक विस्तार से बता सकते हैं कि आप अपने आप को डाउनसम्पलिंग कैसे करते हैं, और आप ओपनगेल को यह कैसे बताते हैं कि (और कब) डाउनस्लेम्ड एटलस का उपयोग करें?
टिम केन

1
@TimKane टाइल्स में स्प्लिट एटलस। प्रत्येक mipmap स्तर के लिए, टाइलों को बिलिनियरली downsample करें, उन्हें संयोजित करें, और mipmap स्तर को पैरामीटर के रूप में निर्दिष्ट करने वाले GPU पर अपलोड करें glTexImage2D()। GPU स्वचालित रूप से स्क्रीन पर ऑब्जेक्ट्स आकार के आधार पर सही स्तर चुनता है।
दानीझार २ '

4

ऐसा लगता है कि यह मुद्दा MSAA के कारण हो सकता है। देखें क्या यह उत्तर और जुड़ा हुआ लेख :

"जब आप MSAA चालू करते हैं, तो यह संभव हो जाता है कि शेडर के लिए नमूनों का निष्पादन हो जो पिक्सेल क्षेत्र के अंदर हो, लेकिन त्रिकोण क्षेत्र से बाहर हो।"

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


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

मैंने हार्डवेयर एंटीलियासिंग को अक्षम कर दिया है लेकिन रक्तस्राव अभी भी बना हुआ है। मैं पहले से ही टुकड़े टुकड़े में देख बनावट कर रहा हूँ।
दानीझार

1

यह एक पुराना विषय है, और मुझे इस विषय की समस्या थी।

मेरी बनावट ठीक थी, लेकिन कैमरा पोजिशन (जिससे मेरे तत्व की स्थिति बदल गई) को इस तरह से लेयर करके:

public static void tween(Camera cam, Direction dir, Vec2 buffer, Vec2 start, Vec2 end) {
    if(step > steps) {
        tweening = false;
        return;
    }

    final float alpha = step/steps;

    switch(dir) {
    case UP:
    case DOWN:
        buffer = new Vec2(start.getX(), Util.lerp(start.getY(), (float)end.getY(), alpha));
        cam.getPosition().set(buffer);
        break;
    case LEFT:
    case RIGHT:
        buffer = new Vec2(Util.lerp(start.getX(), end.getX(), alpha), start.getY());
        cam.getPosition().set(buffer);
        break;
    }

    step += 1;
}

पूरी समस्या Util.lerp () फ्लोट या डबल रिटर्न करती है। यह बुरा था क्योंकि कैमरा ऑफ-ग्रिड का अनुवाद कर रहा था और बनावट के स्निपेट के साथ कुछ अजीब मुद्दे पैदा कर रहा था कि कहां> X में 0 और Y में 0।

TLDR: फ़्लोट्स का उपयोग करते हुए कुछ भी न डालें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.