2011-11-21 17 views
9

मैं दो छवियों के बीच "क्रॉस-ओवर" प्रभाव करने के लिए glReadPixels के साथ एक स्क्रीनशॉट ले रहा हूं।ओपनजीएल ES - glReadPixels

जैम एसडीके सिम्युलेटर पर, स्क्रीनशॉट ठीक लिया जाता है और "क्रॉस-ओवर" प्रभाव इलाज काम करता है: enter image description here

बहरहाल, यह है कि यह कैसे iOS और Android उपकरणों पर दिखता है - भ्रष्ट: http://www.eikona.info/images/81269689420703803966.png

मैं हमेशा आरजीबीए 1 बाइट/चैनल के रूप में स्क्रीन को पढ़ता हूं, documentation says के रूप में यह हमेशा स्वीकार किया जाता है।

uint8* Gfx::ScreenshotBuffer(int& deviceWidth, int& deviceHeight, int& dataLength) { 

    /// width/height 
    deviceWidth = IwGxGetDeviceWidth(); 
    deviceHeight = IwGxGetDeviceHeight(); 
    int rowLength = deviceWidth * 4; /// data always returned by GL as RGBA, 1 byte/each 

    dataLength = rowLength * deviceHeight; 

    // set the target framebuffer to read 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glPixelStorei(GL_PACK_ALIGNMENT, 1); 
    uint8* buffer = new uint8[dataLength]; 
    glReadPixels(0, 0, deviceWidth, deviceHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

    return buffer; 
} 

void Gfx::ScreenshotImage(CIwImage* img, uint8*& pbuffer) { 

    int deviceWidth, deviceHeight, dataLength; 

    pbuffer = ScreenshotBuffer(deviceWidth, deviceHeight, dataLength); 
    img->SetFormat(CIwImage::ABGR_8888); 
    img->SetWidth(deviceWidth); 
    img->SetHeight(deviceHeight); 
    img->SetBuffers(pbuffer, dataLength, 0, 0); 
} 
+1

यदि आप अपना 'अप-डाउन' ब्लॉक हटाते हैं, तो भ्रष्टाचार दूर हो जाता है? बस ऊपर उल्टा? या यह _and_ उल्टा हो गया है? – sarnold

+0

बात यह है कि मेरे पास डिवाइस नहीं है इसलिए मुझे अपने क्लाइंट को भेजने की ज़रूरत है, उसके बाद उसे स्थापित करने और परीक्षण करने की प्रतीक्षा करें ... इसमें सब कुछ हो सकता है :-( –

+0

उपरोक्त टिप्पणियां हैं अब मेरे नए निष्कर्षों को प्रतिबिंबित करने के लिए मेरे संदेश को दोबारा संपादित करने के बाद अप्रासंगिक। –

उत्तर

5

अंत में, यह स्मृति की कमी थी। "नया यूंट 8 [डेटा लम्बाई];" एक मौजूदा सूचक वापस नहीं लौटा, इस प्रकार पूरी प्रक्रिया दूषित हो गई।

टॉमए, बफर को साफ़ करने के आपके विचार ने वास्तव में समस्या को हल करने में मेरी सहायता की। धन्यवाद।

5

एक ड्राइवर बग है कि:

यहाँ स्क्रीनशॉट लेने के लिए इस्तेमाल किया कोड है। इतना ही आसान।

ड्राइवर को वीडियो मेमोरी में सतह की पिच मिली है। आप इसे ऊपरी रेखाओं में स्पष्ट रूप से देख सकते हैं। इसके अलावा छवि के निचले हिस्से में जो कचरा आप देखते हैं वह स्मृति है जहां ड्राइवर सोचता है कि छवि संग्रहित है लेकिन वहां अलग-अलग डेटा हैं। बनावट/Vertex डेटा शायद।

और क्षमा करें, मुझे इसे ठीक करने का कोई तरीका नहीं है। आप एक अलग सतह प्रारूप के साथ या multisampling सक्षम/अक्षम करके बेहतर भाग्य हो सकता है।

+0

मेरी इच्छा है कि यह सच था, भ्रष्टाचार आईओएस और एंड्रॉइड दोनों में स्पष्ट है, इसलिए मेरे पक्ष में कुछ और गलत होना चाहिए ... –

+0

विधेयक, यह एंड्रॉइड पर एक ही एआरएम ड्राइवर के साथ एक ही एसजीएक्स 3 डी-चिप की संभावना है और आईओएस। –

3

मैं के बारे में android या एसडीके का उपयोग कर रहे पता नहीं है, लेकिन आईओएस पर जब मैं एक स्क्रीनशॉट लेने के मैं, अगले पॉट बनावट का आकार बफ़र करना है कुछ इस तरह:

int x = NextPot((int)screenSize.x*retina); 
int y = NextPot((int)screenSize.y*retina); 

void *buffer = malloc(x * y * 4); 

glReadPixels(0,0,x,y,GL_RGBA,GL_UNSIGNED_BYTE,buffer); 

फ़ंक्शन नेक्स्टपॉट सिर्फ मुझे अगला पीओटी आकार देता है, इसलिए यदि स्क्रीन का आकार 320x480 था, तो x, y 512x512 होगा।

शायद आपके बफर के चारों ओर लपेटना क्या है क्योंकि यह एक बड़ा बफर आकार की उम्मीद कर रहा है?

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

1

मेरे पास glReadPixels को ठीक करने का कोई समाधान नहीं है। मेरा सुझाव यह है कि आप स्क्रीन से डेटा को वापस पढ़ने की आवश्यकता से बचने के लिए अपना एल्गोरिदम बदलते हैं।

this page पर एक नज़र डालें। इन लोगों ने फ्लैश में सभी पेज फ्लिप प्रभाव किया है। यह सब 2 डी में है, भ्रम केवल छाया ग्रेडियेंट के साथ हासिल किया जाता है।

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

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

3

मुझे लगता है कि यह हो रहा है कि आप कवर की गई विंडो पर glReadPixels का उपयोग करने का प्रयास कर रहे हैं। यदि दृश्य क्षेत्र शामिल है, तो glReadPixels का परिणाम अपरिभाषित है।

How do I use glDrawPixels() and glReadPixels()? और The Pixel Ownership Problem देखें।

के रूप में कहा here:

समाधान एक गुप्त बफर (FBO) बनाने के लिए और FBO को प्रस्तुत करने के लिए है।

एक और विकल्प यह सुनिश्चित करना है कि जब आप glReadPixels का उपयोग करते हैं तो खिड़की को कवर नहीं किया जाता है।

1

मुझे glReadPixels का उपयोग करके एंड्रॉइड डिवाइस पर किसी भी समस्या के बिना मेरे एंड्रॉइड गेम का स्क्रीनशूट मिल रहा है।

मुझे यकीन नहीं है कि आपके मामले में क्या समस्या है, अधिक जानकारी की आवश्यकता है।

  1. मैं तुम्हें PixelStore प्रारूप निर्दिष्ट करने के लिए नहीं की सिफारिश करेंगे: तो शुरू कर सकते हैं। मैं 1 बाइट में आपके संरेखण के बारे में चिंतित हूं, क्या आप वाकई "इसका इस्तेमाल करते हैं"/"जानते हैं कि यह क्या करता है"? ऐसा लगता है कि आप जो भी निर्दिष्ट करते हैं उसे प्राप्त करते हैं - पूरी तरह से पैक की गई छवि के बजाय एक अतिरिक्त बाइट (अपनी छवि को देखें, वहां एक अतिरिक्त पिक्सेल हमेशा!)। तो इसे हटाने का प्रयास करें:

    glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_PACK_ALIGNMENT, 1);

  2. मैं, सी कोड में यकीन नहीं है के रूप में मैं केवल जावा में काम कर रहा था, लेकिन यह संभव बिंदु के रूप में दिखता है:

    // चौड़ाई/ऊंचाई deviceWidth = IwGxGetDeviceWidth(); डिवाइसहेइट = IwGxGetDeviceHeight();

क्या आपको डिवाइस का आकार मिल रहा है? आप इस तरह अपने ओपन सतह आकार का उपयोग करना चाहिए,:

public void onSurfaceChanged(GL10 gl, int width, int height) { 
int surfaceWidth = width; 
int surfaceHeight = height; 
} 
  1. आप अगले पर कब्जा कर लिया छवि के साथ क्या कर रहे हो? क्या आप जानते हैं कि ओपनजीएल से मिले मेमोरी ब्लॉक आरजीबीए है, लेकिन सभी गैर-ओपनजी छवि संचालन एआरजीबी की उम्मीद करते हैं? उदाहरण के लिए यहां आपके कोड में आप अल्फा को पहले बिट होने की उम्मीद करते हैं, अंतिम नहीं:

    img-> SetFormat (CIwImage :: ABGR_8888);

  2. यदि 1, 2 और 3 की मदद नहीं की गई है तो आप बाद में जांच करने के लिए कैप्चर की गई स्क्रीन को एसडीकार्ड पर सहेज सकते हैं। मेरे पास एक प्रोग्राम है जो पीसी पर जांच करने के लिए ओपनगल आरजीबीए ब्लॉक को सामान्य बिटमैप में परिवर्तित करता है। मैं इसे आपके साथ साझा कर सकता हूं।