2012-04-06 18 views
27

मैं 2 डी इंजन पर काम कर रहा हूं। यह पहले से ही काफी अच्छा काम करता है, लेकिन मुझे पिक्सेल-त्रुटियां मिल रही हैं।ओपनगल पिक्सेल सही 2 डी ड्राइंग

उदाहरण के लिए, मेरी विंडो 960x540 पिक्सेल है, मैं (0, 0) से (95 9, 0) तक एक रेखा खींचता हूं। मैं उम्मीद करता हूं कि स्कैन-लाइन 0 पर प्रत्येक पिक्सेल रंग पर सेट हो जाएगा, लेकिन नहीं: सही-पिक्सेल खींचा नहीं गया है। जब मैं पिक्सेल 539 पर लंबवत रूप से खींचता हूं तो वही समस्या। मुझे इसे खींचने के लिए वास्तव में (960, 0) या (0, 540) आकर्षित करने की आवश्यकता है।

जैसा कि मैं पिक्सेल युग में पैदा हुआ था, मुझे विश्वास है कि यह सही परिणाम नहीं है। जब मेरी स्क्रीन 320x200 पिक्सल बड़ी थी, तो मैं 0 से 319 तक और 0 से 199 तक खींच सकता था, और मेरी स्क्रीन पूरी हो जाएगी। अब मैं एक स्क्रीन के साथ एक दाएं/नीचे पिक्सेल खींचा नहीं है।

यह विभिन्न चीजों के कारण हो सकता है: जहां मुझे उम्मीद है कि ओपनगल लाइन आदिम को पिक्सेल से पिक्सेल तक खींचा जा सकता है, आखिरी पिक्सेल वास्तव में अनन्य है? क्या यही है? मेरा प्रक्षेपण मैट्रिक्स गलत है? मैं झूठी धारणा के तहत हूं कि जब मेरे पास 960x540 का बैकबफर है, तो वास्तव में एक पिक्सल अधिक है? कुछ और?

क्या कोई मेरी मदद कर सकता है? मैं अब इस समस्या को लंबे समय से देख रहा हूं, और हर बार जब मैंने सोचा कि यह ठीक है, तो मैंने थोड़ी देर बाद देखा कि यह वास्तव में नहीं था।

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

int width = resX(); 
int height = resY(); 

for (int i = 0; i < height; i += 2) 
    rm->line(0, i, width - 1, i, vec4f(1, 0, 0, 1)); 
for (int i = 1; i < height; i += 2) 
    rm->line(0, i, width - 1, i, vec4f(0, 1, 0, 1)); 

// when I do this, one pixel to the right remains undrawn 

void rendermachine::line(int x1, int y1, int x2, int y2, const vec4f &color) 
{ 
    ... some code to decide what std::vector the coordinates should be pushed into 
    // m_z is a z-coordinate, I use z-buffering to preserve correct drawing orders 
    // vec2f(0, 0) is a texture-coordinate, the line is drawn without texturing 
    target->push_back(vertex(vec3f((float)x1 + 0.375f, (float)y1 + 0.375f, m_z), color, vec2f(0, 0))); 
    target->push_back(vertex(vec3f((float)x2 + 0.375f, (float)y2 + 0.375f, m_z), color, vec2f(0, 0))); 
} 

void rendermachine::update(...) 
{ 
    ... render target object is queried for width and height, in my test it is just the back buffer so the window client resolution is returned 
    mat4f mP; 
    mP.setOrthographic(0, (float)width, (float)height, 0, 0, 8000000); 

    ... all vertices are copied to video memory 

    ... drawing 
    if (there are lines to draw) 
     glDrawArrays(GL_LINES, (int)offset, (int)lines.size()); 

    ... 
} 

// And the (very simple) shader to draw these lines 

// Vertex shader 
    #version 120 
    attribute vec3 aVertexPosition; 
    attribute vec4 aVertexColor; 
    uniform mat4 mP; 
    varying vec4 vColor; 
    void main(void) { 
     gl_Position = mP * vec4(aVertexPosition, 1.0); 
     vColor = aVertexColor; 
    } 

// Fragment shader 
    #version 120 
    #ifdef GL_ES 
    precision highp float; 
    #endif 
    varying vec4 vColor; 
    void main(void) { 
     gl_FragColor = vColor.rgb; 
    } 
+0

मुझे लगता है कि यह "बिंदु विशेष" चीज है जिसके बारे में मैं बात कर रहा हूं। यदि आप पंक्तियों को आकर्षित करने के लिए क्यूटी या सी ++ बिल्डर/डेल्फी या यहां तक ​​कि विंडोज एपीआई का उपयोग करते हैं, तो पिक्सेल अंत-बिंदु को छोड़कर खींचे जाते हैं। तो यह संभव है कि ओपनएल में भी किया जाता है, और शायद त्रिभुजों को चित्रित करते समय भी? जब आप क्यूटी, बिल्डर, ... के साथ एक आयताकार खींचते हैं, तो आपको नीचे दाएं कोने को भी बाहर रखा जाता है ... – scippie

+0

निम्न परीक्षण ऊपर बताए गए समझौते के साथ अनुबंध दिखाता है: जब मैं खिड़की के सभी कोनों पर पिक्सल भरने के लिए जीएल_POINT का उपयोग करता हूं, तो ये निर्देशांक होते हैं क्योंकि मैं उन्हें उम्मीद करता हूं: (0,0), (चौड़ाई -1, ऊंचाई -1)। यह मुझे दिखाता है कि ड्राइंग का मेरा तरीका सही है और उस रेखा (और संभवतः त्रिकोण) में अंत-बिंदु शामिल नहीं होगा। क्या कोई सहमत हो सकता है? – scippie

+0

संबंधित http://stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d –

उत्तर

15

ओपनजीएल में, लाइनों को "डायमंड एक्जिट" नियम का उपयोग करके रास्टरराइज किया जाता है। यह है लगभग ही कह अंत अनन्य है समन्वय, लेकिन काफी नहीं ...

यह वही ओपन कल्पना में क्या कहना है है कि के रूप में: http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html

इसके अलावा ओपन पूछे जाने वाले प्रश्न पर एक नजर है , http://www.opengl.org/archives/resources/faq/technical/rasterization.htm, आइटम "14.0 9 0 मैं लाइनों के सटीक पिक्सेलकरण कैसे प्राप्त करूं?"। यह कहता है "ओपनजीएल विनिर्देश लाइन रेंडरिंग हार्डवेयर की एक विस्तृत श्रृंखला के लिए अनुमति देता है, इसलिए सटीक पिक्सेलकरण संभव नहीं हो सकता है।"

कई लोग तर्क देंगे कि आपको ओपनजीएल में लाइनों का उपयोग नहीं करना चाहिए। उनका व्यवहार इस बात पर आधारित है कि कैसे प्राचीन एसजीआई हार्डवेयर काम करता था, न कि समझ में आता है। (और चौड़ाई वाली रेखाएं> 1 अच्छी तरह से दिखने के तरीके में उपयोग करने के लिए लगभग असंभव हैं!)

+0

धन्यवाद, यह उत्तर बहुत उपयोगी है! लाइनें परीक्षण उद्देश्यों के लिए हैं, अंतिम उत्पाद शीतलता के लिए नहीं। तो मैं इस बिंदु पर GL_LINES से बहुत खुश हूं। क्या मैं मान सकता हूं कि त्रिकोणों का एक ही परिणाम है? मेरा मतलब है, अगर मैं दो त्रिभुजों को चित्रित करके एक भरे आयताकार खींचता हूं, तो क्या मैं एक ही परिणाम की उम्मीद कर सकता हूं? – scippie

+3

क्षमा करें: 14.120: भरने वाले प्राइमेटिव्स और लाइन प्राइमेटिव रास्टरराइजेशन के लिए अलग-अलग नियमों का पालन करते हैं। – scippie

+0

> "और चौड़ाई वाली रेखाएं> 1 अच्छे तरीके से उपयोग करने के लिए लगभग असंभव हैं!" कोई उन्हें पतली आयतों के रूप में खींच सकता है और फिर लगभग किसी भी दृश्य गुणों के साथ लाइन के रूप में दिखने के लिए टुकड़े टुकड़े में कुछ जादू कर सकता है। लेकिन यह महंगा हो सकता है। –

6

ध्यान दें कि अंतरिक्ष समन्वय ओपन पूर्णांकों का बोध भी नहीं है, सब कुछ एक नाव और एक ओपन पिक्सेल का "केन्द्र" है वास्तव में अपने ऊपरी-बाएं कोने के बजाय 0.5,0.5 पर है। इसलिए, यदि आप 1 जीएक्स चौड़ी लाइन 0,0 से 10,10 समेत चाहते हैं, तो आपको वास्तव में 0.5,0.5 से 10.5,10.5 तक एक रेखा खींचना था।

यह विशेष रूप से स्पष्ट होगा यदि आप एंटी-एलाइजिंग चालू करते हैं, यदि आपके पास एंटी-एलाइजिंग है और आप 50,0 से 50,100 तक आकर्षित करने का प्रयास करते हैं तो आप एक धुंधली 2 पीएक्स चौड़ी रेखा देख सकते हैं क्योंकि रेखा दो के बीच में गिर गई पिक्सल।

+1

मैं पूरी तरह से समझता हूं कि आप किस बारे में बात कर रहे हैं लेकिन यह कोई मुद्दा नहीं है। सही प्रोजेक्शन मैट्रिक्स का उपयोग करके और प्रत्येक पिक्सेल में 0.375 जोड़कर, एटीआई और एनवीडिया दोनों संख्याओं को गोल करेंगे ताकि निर्देशांक सटीक पिक्सल हों। उदाहरण के लिए मैक ओएस पिक्सेल सही खिड़कियों को कैसे आकर्षित करेगा यदि वे पिक्सेल सही नहीं थे? – scippie

+0

@scippie: आपको वास्तव में 0.5 जोड़ना चाहिए। 0.5 पिक्सेल के बीच है। 0.375 नहीं है। – SigTerm

+4

@ सिगटर्म: यह सच नहीं है, आपको इसे अति और एनवीडिया हार्डवेयर दोनों पर आज़माएं और दुःस्वप्न शुरू हो जाए। अति और एनवीडिया अलग-अलग दौर। 0.375 का उपयोग करके, गोल दोनों दोनों पर समान है और परिणाम सही हैं (हालांकि यह सैद्धांतिक रूप से सही नहीं हो सकता है) – scippie

संबंधित मुद्दे