I have camera that renders to a RenderTexture. I would like to pass the contents of the RenderTexture to a native plugin. From the Unity’s native plugin example, a native plugin can only handle ID3D11Texture2D pointers which correspond to Unity’s Texture2D.GetNativeTexturePtr objects. Therefore, I have a functional version whereby the RenderTexture’s output is first copied to a Texture2D with ReadPixels:
private IEnumerator DoEveryFrame()
{
//Wait for graphics to render
yield return new WaitForEndOfFrame();
// Remember current render textures
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture currentCamRT = cam.targetTexture;
// Force rendering of the camera to my render texture
cam.targetTexture = rt;
cam.Render(); // 2nd Render seems to be necessary, but why??
cam.targetTexture = currentCamRT;
// Get a copy of the rendered data
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
screenShot.Apply(); // hits perf significantly but needed otherwise actual copy does not occur
// Restorie previously assigned render texture
RenderTexture.active = currentActiveRT;
//Destroy(rt);
// Issue a plugin event with arbitrary integer identifier.
// The plugin can distinguish between different
// things it needs to do based on this ID.
// For our simple plugin, it does not matter which ID we pass here.
GL.IssuePluginEvent (200);
}
Unfortunately, this method of using ReadPixels() and then Apply() significantly hurts performance. I don’t actually need the contents of RenderTexture on the CPU. How can I accomplish either of the following:
- [Preferred] Pass a valid reference to the RenderTexture directly to the native plugin without any data copying. This would be ideal. However, using RenderTexture.GetNativeTexturePtr resulted in all-black texture as seen by native plugin.
- Make a GPU-to-GPU copy of Render Texture to Texture2D. A copy is still involved, but at least it is not crossing the bus.
My second minor question is why do I need to perform a second Camera.Render()? Why doesn’t this work:
RenterTexture.active = cam.targetTexture;
screenShot.ReadPixels(...);
screenShot.Apply();
This must be doable; I’m just missing the magic invocation…