/// RenderTextureReader reads a RenderTexture from the GPU each frame and passes the data back through a provided callback.
/// </summary>
/// <typeparam name="T">The type of the raw texture data to be provided.</typeparam>
public class RenderTextureReader < T > : IDisposable where T : struct
class RenderTextureReader < T > : IDisposable where T : struct
Action < int , NativeArray < T > , RenderTexture > m_ImageReadCallback ;
int m_NextFrameToCapture ;
Camera m_CameraRenderingToSource ;
/// <param name="cameraRenderingToSource">The <see cref="Camera"/> which renders to the given renderTexture. This is used to determine when to read from the texture.</param>
/// <param name="imageReadCallback">The callback to call after reading the texture</param>
public RenderTextureReader ( RenderTexture source , Camera cameraRenderingToSource , Action < int , NativeArray < T > , RenderTexture > imageReadCallback )
public RenderTextureReader ( RenderTexture source )
m_ImageReadCallback = imageReadCallback ;
m_CameraRenderingToSource = cameraRenderingToSource ;
m_NextFrameToCapture = Time . frameCount ;
RenderPipelineManager . endFrameRendering + = OnEndFrameRendering ;
void OnEndFrameRendering ( ScriptableRenderContext context , Camera [ ] cameras )
public void Capture ( ScriptableRenderContext context , Action < int , NativeArray < T > , RenderTexture > imageReadCallback )
#if UNITY_EDITOR
if ( UnityEditor . EditorApplication . isPaused )
return ;
#endif
if ( ! cameras . Contains ( m_CameraRenderingToSource ) )
return ;
if ( m_NextFrameToCapture > Time . frameCount )
return ;
m_NextFrameToCapture = Time . frameCount + 1 ;
// #if UNITY_EDITOR
// if (UnityEditor.EditorApplication.isPaused)
// return;
// #endif
// if (!cameras.Contains(m_CameraRenderingToSource))
// return;
//
// if (m_NextFrameToCapture > Time.frameCount)
// return;
//
// m_NextFrameToCapture = Time.frameCount + 1;
if ( ! GraphicsUtilities . SupportsAsyncReadback ( ) )
{
0 , 0 ) ;
RenderTexture . active = null ;
var data = m_CpuTexture . GetRawTextureData < T > ( ) ;
m_I mageReadCallback( Time . frameCount , data , m_Source ) ;
i mageReadCallback( Time . frameCount , data , m_Source ) ;
commandBuffer . RequestAsyncReadback ( m_Source , r = > OnGpuReadback ( r , frameCount ) ) ;
commandBuffer . RequestAsyncReadback ( m_Source , r = > OnGpuReadback ( r , frameCount , imageReadCallback ) ) ;
context . ExecuteCommandBuffer ( commandBuffer ) ;
context . Submit ( ) ;
CommandBufferPool . Release ( commandBuffer ) ;
void OnGpuReadback ( AsyncGPUReadbackRequest request , int frameCount )
void OnGpuReadback ( AsyncGPUReadbackRequest request , int frameCount ,
Action < int , NativeArray < T > , RenderTexture > imageReadCallback )
else if ( request . done & & m_ImageReadCallback ! = null )
else if ( request . done & & imageReadCallback ! = null )
m_ImageReadCallback ( frameCount , request . GetData < T > ( ) , m_Source ) ;
imageReadCallback ( frameCount , request . GetData < T > ( ) , m_Source ) ;
}
}
public void Dispose ( )
{
WaitForAllImages ( ) ;
RenderPipelineManager . endFrameRendering - = OnEndFrameRendering ;
if ( m_CpuTexture ! = null )
{
Object . Destroy ( m_CpuTexture ) ;