Unity 4 BETA: iOS: Texture2D ReadPixels not responding to bound framebuffer

In Unity 3.x/iOS I’ve had success with retrieving texture data from an image rendered on the device with the following process:

[Unity]

  • Create Texture2D
  • Pass texture handle to device

[Device/OpenGL]

  • Create frame buffer and bind texture
  • Do custom texture rasterisation into framebuffer

[Unity]

  • Set texture framebuffer as active
  • Call ReadPixels() on Texture2D to pull hardware texture into memory
  • Restore Unity/native framebuffer

Now using the Unity 4.x BETA/iOS ReadPixels() pulls in the full Unity scene render and not just my custom stuff. After reading the docs (again) there is a mention that ReadPixels() on mobile devices is deferred until the end of the frame, so I’ve tried a co-routine approach with WaitTillEndOfFrame() and that still brings in the full Unity scene render.

I’ve also had a tinker with Render Textures but they aren’t responding at all (there should be no need for a RenderTexture as I just need a hardware texture handle).

I’m wondering if there is a change in ReadPixels() that forces a read from the Unity context (even though I’m explicitly telling OpenGL to set my framebuffer as the active framebuffer) and overriding my approach? I think I’ve tried everything to counter any possible timing issues…

Any suggestions would be greatly appreciated!

So I’ve hacked a fix!

The problem is down to forcing my framebuffer to stick whilst calling ReadPixels; so what I do is create a placeholder RenderTexture (min OpenGL 64x64) to be the context, then wrap my old calls with setting the RenderTexture to active to stave off any errant Unity under-the-hood-jiggery-pokery!

Scraping the barrel, but it works, ‘fixes’ in bold (note use of RenderTexture means this is a Pro only hack):

[Unity]

  • Create Texture2D
  • Pass texture handle to device

[Device/OpenGL]

  • Create frame buffer and bind texture
  • Do custom texture rasterisation into framebuffer

[Unity]

  • Create temp RenderTexture
  • Set RenderTexture.active to temp RenderTexture
  • Set texture framebuffer as active
  • Call ReadPixels() on Texture2D to pull hardware texture into memory
  • Restore Unity/native framebuffer
  • Set RenderTexture.active to null
  • Release RenderTexture