2015-05-09 146 views
1

我試圖在Unity3D(C#)中的OpenGL中實現glReadPixels函數。Unity3D glReadPixels崩潰

public IntPtr buffer; 
private const int GL_RGBA     = 0x1908; 
private const int GL_UNSIGNED_BYTE   = 0x1401; 

[DllImport("/System/Library/Frameworks/OpenGL.framework/OpenGL")] 
public static extern void glReadPixels (int x, int y, int width, int height, int format, int type, IntPtr buffer); 

這是內存分配:

byte[] information=new byte[20*20*3]; 
IntPtr unmanagedPointer = Marshal.AllocHGlobal(information.Length); 
Marshal.Copy(information, 0, unmanagedPointer, information.Length); 

那麼,在這個腳本連接到相機,我手動調用

GetComponent<Camera>().Render(); 

而且,在OnPostRender:

void OnPostRender() { 
    glReadPixels (0, 0, 20, 20, GL_RGBA, GL_UNSIGNED_BYTE, unmanagedPointer); 
} 

但是,Unity3D編輯器崩潰並沒有其他線索可以確切地知道發生了什麼。 我不知道如果我需要做其他任何事情來使用OpenGL函數。

編輯:這是團結的崩潰報告:

1 libsystem_c.dylib    0x00007fff91bd9b73 abort + 129 
2 com.unity3d.UnityEditor5.x  0x0000000100718ae7 HandleSignal(int, __siginfo*, void*) + 1031 
3 libmono.0.dylib     0x00000001056738e2 mono_chain_signal + 71 
4 libmono.0.dylib     0x00000001055c0f37 mono_sigsegv_signal_handler + 213 
5 libsystem_platform.dylib  0x00007fff91ca1f1a _sigtramp + 26 
6 libGLImage.dylib    0x00007fff8e6a381f storeVecColor + 2975 
7 libGLImage.dylib    0x00007fff8e6b17a2 glgProcessColor + 14610 
8 libGLImage.dylib    0x00007fff8e685104 __glgProcessPixelsWithProcessor_block_invoke + 108 
9 libdispatch.dylib    0x00007fff884f5344 _dispatch_client_callout2 + 8 
10 libdispatch.dylib    0x00007fff884f5873 _dispatch_apply_serial + 42 
11 libdispatch.dylib    0x00007fff884e9c13 _dispatch_client_callout + 8 
12 libdispatch.dylib    0x00007fff884f49a1 _dispatch_sync_f_invoke + 39 
13 libdispatch.dylib    0x00007fff884f4f60 dispatch_apply_f + 290 
14 libGLImage.dylib    0x00007fff8e684ece glgProcessPixelsWithProcessor + 6869 
15 com.apple.GeForceTeslaGLDriver 0x000ea0 0x123440000000 + 3219104 
16 GLEngine      0x00007fff923acbf8 glReadPixels_Exec + 1390 
17 libGL.dylib      0x00007fff91770bd5 glReadPixels + 57 

UPDATE:最後,我設法修復崩潰。 unmanagedPointer未正確分配。但是,內存分配仍然存在一些問題。如果我在Update()上渲染攝像頭(在OnPostRender上調用glReadPixels),Unity會在約3-4秒後崩潰。

正如你可以在這個崩潰報告看:

6 libGPUSupport.dylib    0x00000001188a627d 
gpulCheckForFramebufferIOSurfaceChanges + 54 
7 libGPUSupport.dylib    0x00000001188a6202 gldUpdateReadFramebuffer + 42 
8 GLEngine      0x00007fff9247e01c gleUpdateReadFramebufferState + 425 
9 GLEngine      0x00007fff923ac751 glReadPixels_Exec + 

它似乎有事情做與gpulCheckForFramebuffer。 有什麼想法?

+2

我想你實際上在glReadPixels緩衝區中分配內存以複製到? IIRC glReadPixels從當前幀緩衝區中讀取數據。你真的知道是否有一個界限?這似乎是想要做的一件非常奇怪的事情。爲什麼不使用現有的Unity方法之一(Application.CaptureScreenshot,RenderTexture或Texture2D.ReadPixels)。 – user673679

+0

我將第二條關於爲glReadPixels分配緩衝區的說法:看起來像你沒有,你絕對應該。另外,你確定你有OpenGL模式下運行的Unity(即通過使用命令行參數),而不是默認的D3D渲染管道?最後但並非最不重要的:請告訴我們更多關於你想用glReadPixels實現的內容。可能有更好的方法來實現你的目標。 –

+0

我正在使用正射相機來切換遠近屬性的場景。我開始使用Texture2D.ReadPixels,但它非常緩慢。我讀了這個方法的速度更快,但我仍然試圖實現它。我肯定認爲崩潰與內存分配有關。我已經使用我現在使用的代碼更新了該文章。謝謝! – pabgn

回答

2

您沒有爲結果分配足夠的內存。您分配每個象素3個字節爲您的20x20的圖像:

byte[] information=new byte[20*20*3]; 

但對於glReadPixels()呼叫,您指定的GL_RGBA格式:每像素

glReadPixels (0, 0, 20, 20, GL_RGBA, GL_UNSIGNED_BYTE, information); 

當與GL_RGBA格式讀取,4個字節會寫入所提供的目的地(R,G,B和A各一個字節)。

你要麼需要每像素分配4個字節:

byte[] information = new byte[20 * 20 * 4]; 

或格式更改爲GL_RGB,這需要每個像素只有3個字節的結果:

glReadPixels(0, 0, 20, 20, GL_RGB, GL_UNSIGNED_BYTE, information); 
+1

謝謝你的回覆。我剛剛更改了緩衝區,並仍然使用之前發佈的同一報告D: – pabgn

+0

此問題的任何進展?我在OSX上也有這個問題。在Android上?這也可以做到嗎? –