2011-11-21 186 views
9

我正在用glReadPixels進行截圖,以在兩幅圖像之間執行「交叉」效果。OpenGL ES - glReadPixels

在果醬SDK模擬器截圖取就好了和「交叉」效果的作品一種享受: enter image description here

然而,這是它的外觀上的iOS和Android設備 - 損壞: http://www.eikona.info/images/81269689420703803966.png

我總是閱讀屏幕RGBA 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

如果你刪除你的'up-down'塊,腐敗消失了嗎?只是倒過來?還是它被顛倒了? – sarnold

+0

事情是,我沒有設備,所以我需要發送給我的客戶,然後等待他安裝和測試......所有這些可能需要幾天時間:-( –

+0

上述評論是現在無需重新編輯我的消息,以反映我的新發現 –

回答

5

最後,它是內存不足。 「new uint8 [dataLength];」從來沒有返回一個存在的指針,因此整個過程都被破壞了。

TomA,您清理緩衝區的想法實際上幫助我解決了這個問題。謝謝。

5

這是一個驅動程序的bug。就那麼簡單。

驅動程序錯誤地獲取了視頻內存中曲面的音高。您可以在上面的行中清楚地看到這一點。此外,您在圖像下部看到的垃圾是驅動程序認爲存儲圖像的內存,但是存在不同的數據。紋理/頂點數據也許。

對不起,我知道沒有辦法解決這個問題。使用不同的曲面格式或啓用/禁用多重採樣可能會帶來更好的運氣。

+0

我希望這是真實的,在iOS和Android都會出現這種腐敗現象,所以在我身邊肯定有其他的錯誤... –

+0

比爾,它很可能是相同的SGX 3D芯片,在Android上具有相同的ARM驅動程序, iOS版。 –

3

我不知道Android或正在使用的SDK,但在IOS時,我採取截圖我必須使緩衝區中的下POT紋理的大小,像這樣:

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); 

NextPot函數只給我下一個POT大小,所以如果屏幕大小是320x480,那麼x,y就是512x512。

也許你看到的是緩衝區的包裝,因爲它期待更大的緩衝區大小?

此外,這可能是它在模擬器中而不是在設備上工作的原因,我的顯卡沒有POT大小限制,並且我得到了類似(看起來很奇怪)的結果。

1

我沒有固定glReadPixels的解決方案。我的建議是,你改變你的算法,以避免需要從屏幕上讀回數據。

看看this page。這些人在Flash中完成了翻頁效果。全都是二維的,幻影只是用陰影漸變實現的。

我想你可以使用類似的方法,但在3D中稍好一點。基本上你必須將效果分成三部分:正面朝上的首頁(雲),底部頁面(女孩)和首頁的背面。您必須分別繪製每個部分。您可以在同一屏幕中輕鬆地將正面朝上的首頁和底部頁面繪製在一起,您只需調用每個預設裁剪區域的繪圖代碼,該區域與首頁彎曲的分割線對齊。在繪製頂部和底部頁面之後,您可以在頂部繪製灰色的背面部分,也與分割線對齊。

使用這種方法,你只會失去一點變形,雲圖像開始向上彎曲,當然我的方法不會發生變形。希望這樣做不會降低效果,我認爲陰影對於提供深度效果更重要,並且會隱藏這種微小的不一致。

3

我認爲正在發生的事情是您正試圖在覆蓋的窗口上使用glReadPixels。如果查看區域被覆蓋,則glReadPixels的結果未定義。

請參閱How do I use glDrawPixels() and glReadPixels()?The Pixel Ownership Problem

正如所述here

的解決方案是使離屏緩衝器(FBO)和渲染到 FBO。

另一種選擇是確保當您使用glReadPixels時窗口不被覆蓋。

1

我正在使用glReadPixels的android設備上沒有任何問題,我的android遊戲的屏幕截圖。

我不確定你的情況是什麼問題,需要更多的信息。 所以,讓我們開始:

  1. 我建議你不要指定PixelStore格式。我擔心你在1字節中的對齊,你真的「使用它」/「知道它做了什麼」?看起來你得到了你指定的東西 - 一個額外的字節(看你的圖像,一個額外的像素一直!),而不是完整打包的圖像。所以試圖刪除它:

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

  2. 我不知道在C代碼,如我的工作只在Java中,但是這看起來儘可能點:

    //寬度/高度 deviceWidth = IwGxGetDeviceWidth(); deviceHeight = IwGxGetDeviceHeight();

您是否正在獲取設備尺寸?你應該用你的OpenGL面的大小,類似這樣的:

public void onSurfaceChanged(GL10 gl, int width, int height) { 
int surfaceWidth = width; 
int surfaceHeight = height; 
} 
  1. 你在接下來拍攝的圖像在做什麼?你知道你從opengl獲得的內存塊是RGBA,但是所有非opengl圖像操作都期望ARGB? 例如,在您的代碼中,您希望alpha是第一位,而不是最後一位:

    img-> SetFormat(CIwImage :: ABGR_8888);

  2. 如果1,2和3沒有幫助,您可能想要將捕獲的屏幕保存到手機SD卡中以供日後檢查。我有一個程序,將opengl RGBA塊轉換爲普通位圖,在PC上進行檢查。我可能會與你分享。