using UnityEngine;
namespace MLAgents.Sensors
{
///
/// Sensor class that wraps a instance.
///
public class RenderTextureSensor : ISensor
{
RenderTexture m_RenderTexture;
bool m_Grayscale;
string m_Name;
int[] m_Shape;
SensorCompressionType m_CompressionType;
///
/// Initializes the sensor.
///
/// The instance to wrap.
/// Whether to convert it to grayscale or not.
/// Name of the sensor.
/// Compression method for the render texture.
public RenderTextureSensor(
RenderTexture renderTexture, bool grayscale, string name, SensorCompressionType compressionType)
{
m_RenderTexture = renderTexture;
var width = renderTexture != null ? renderTexture.width : 0;
var height = renderTexture != null ? renderTexture.height : 0;
m_Grayscale = grayscale;
m_Name = name;
m_Shape = new[] { height, width, grayscale ? 1 : 3 };
m_CompressionType = compressionType;
}
///
public string GetName()
{
return m_Name;
}
///
public int[] GetObservationShape()
{
return m_Shape;
}
///
public byte[] GetCompressedObservation()
{
using (TimerStack.Instance.Scoped("RenderTextureSensor.GetCompressedObservation"))
{
var texture = ObservationToTexture(m_RenderTexture);
// TODO support more types here, e.g. JPG
var compressed = texture.EncodeToPNG();
UnityEngine.Object.Destroy(texture);
return compressed;
}
}
///
public int Write(WriteAdapter adapter)
{
using (TimerStack.Instance.Scoped("RenderTextureSensor.Write"))
{
var texture = ObservationToTexture(m_RenderTexture);
var numWritten = Utilities.TextureToTensorProxy(texture, adapter, m_Grayscale);
UnityEngine.Object.Destroy(texture);
return numWritten;
}
}
///
public void Update() {}
///
public SensorCompressionType GetCompressionType()
{
return m_CompressionType;
}
///
/// Converts a RenderTexture to a 2D texture.
///
/// The 2D texture.
/// RenderTexture.
/// Texture2D to render to.
public static Texture2D ObservationToTexture(RenderTexture obsTexture)
{
var height = obsTexture.height;
var width = obsTexture.width;
var texture2D = new Texture2D(width, height, TextureFormat.RGB24, false);
var prevActiveRt = RenderTexture.active;
RenderTexture.active = obsTexture;
texture2D.ReadPixels(new Rect(0, 0, texture2D.width, texture2D.height), 0, 0);
texture2D.Apply();
RenderTexture.active = prevActiveRt;
return texture2D;
}
}
}