static void SetupAlternateGetBlockSize() { _blockSizeMap = new Dictionary <GraphicsFormat, int>(); foreach (GraphicsFormat format in Enum.GetValues(typeof(GraphicsFormat))) { _blockSizeMap[format] = (int)GraphicsFormatUtility.GetBlockSize(format); _componentCountMap[format] = (int)GraphicsFormatUtility.GetComponentCount(format); } }
/// <summary> /// Get the number of components for a given format. /// </summary> /// <param name="format">Graphics format you are using.</param> /// <returns>Returns the number of components.</returns> public static int GetComponentCount(GraphicsFormat format) { #if UNITY_2019_3_OR_NEWER return((int)GraphicsFormatUtility.GetComponentCount(format)); #else if (!_componentCountMap.ContainsKey(format)) { throw new NotSupportedException("ComponentCountMap doesn't contain key for format"); } return(_componentCountMap[format]); #endif }
// formats with higher sorting code appear first on the dropdown lists static uint GetSortCodeForFormat(TextureFormat fmt) { var f = GraphicsFormatUtility.GetGraphicsFormat(fmt, false); // first by: normalized, floating point, integer uint type; if (GraphicsFormatUtility.IsNormFormat(f)) { type = 3; } else if (GraphicsFormatUtility.IsHalfFormat(f) || GraphicsFormatUtility.IsFloatFormat(f)) { type = 2; } else if (GraphicsFormatUtility.IsIntegerFormat(f)) { type = 1; } else { type = 0; } // then by component count: RGBA, RGB, RG, R/A var components = GraphicsFormatUtility.GetComponentCount(f); // then compression: first compressed regular, then compressed Crunch, then uncompressed uint compression = 0; if (GraphicsFormatUtility.IsCompressedFormat(f)) { compression++; if (!GraphicsFormatUtility.IsCrunchFormat(fmt)) { compression++; } } return((type << 24) | (components << 16) | (compression << 8)); }
/// <summary> /// Perform the readback from the provided Render texture using ReadPixels API. /// </summary> /// <param name="renderTexture">Input source Render texture for the readback.</param> /// <returns>Returns a byte array of the RGB data retrieved from the readback.</returns> /// <exception cref="NotSupportedException"></exception> public static byte[] GetPixelsSlow(RenderTexture renderTexture) { var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(renderTexture.format, false); var pixelSize = GraphicsUtilities.GetBlockSize(graphicsFormat); var channels = GraphicsFormatUtility.GetComponentCount(graphicsFormat); var channelSize = pixelSize / channels; var rect = new Rect(0, 0, renderTexture.width, renderTexture.height); // for RGB(A) we can just return the raw data. if (channels >= 3 && channels <= 4) { var texture = new Texture2D(renderTexture.width, renderTexture.height); RenderTexture.active = renderTexture; texture.ReadPixels(rect, 0, 0); RenderTexture.active = null; var data = texture.GetRawTextureData(); UnityEngine.Object.Destroy(texture); return(data); } else { Debug.Assert(channels == 1, "Can only handle a single channel RT."); // Read pixels must be one of RGBA32, ARGB32, RGB24, RGBAFloat or RGBAHalf. // So R16 and RFloat will be converted to RGBAFloat. var texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBAFloat, false); RenderTexture.active = renderTexture; texture.ReadPixels(rect, 0, 0); RenderTexture.active = null; var length = renderTexture.width * renderTexture.height; var input = ArrayUtilities.Cast <float>(texture.GetRawTextureData()); UnityEngine.Object.Destroy(texture); Array output = null; int index = 0; switch (channelSize) { case 2: short[] shorts = ArrayUtilities.Allocate <short>(length); var si = 0; var numerator = (1 << 16) - 1; while (index < length) { shorts[index++] = (short)(numerator * input[si]); si += 4; } output = shorts; break; case 4: float[] floats = ArrayUtilities.Allocate <float>(length); var fi = 0; while (index < length) { floats[index++] = input[fi]; fi += 4; } output = floats; break; default: throw new NotSupportedException(); } return(ArrayUtilities.Cast <byte>(output)); } }
private void ProcessBatch() { while (_requestsBatch.Count > 0) { var request = _requestsBatch.Dequeue(); var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(request.renderTexture.format, false); var pixelSize = GraphicsFormatUtility.GetBlockSize(graphicsFormat); var channels = GraphicsFormatUtility.GetComponentCount(graphicsFormat); var channelSize = pixelSize / channels; var rect = new Rect(0, 0, request.renderTexture.width, request.renderTexture.height); if (channels >= 3 && channels <= 4) { if (request.texture == null) { request.texture = new Texture2D(request.renderTexture.width, request.renderTexture.height, request.renderTexture.graphicsFormat, TextureCreationFlags.None); } RenderTexture.active = request.renderTexture; request.texture.ReadPixels(rect, 0, 0); request.InvokeCallback(request.texture.GetRawTextureData()); RenderTexture.active = null; } else { Debug.Assert(channels == 1, "Can only handle a single channel RT."); // Read pixels must be one of RGBA32, ARGB32, RGB24, RGBAFloat or RGBAHalf. // So R16 and RFloat will be converted to RGBAFloat. var texture = new Texture2D(request.renderTexture.width, request.renderTexture.height, TextureFormat.RGBAFloat, false); RenderTexture.active = request.renderTexture; texture.ReadPixels(rect, 0, 0); RenderTexture.active = null; var length = request.renderTexture.width * request.renderTexture.height; var input = ArrayUtilities.Cast <float>(texture.GetRawTextureData()); UnityEngine.Object.Destroy(texture); int index = 0; switch (channelSize) { case 2: short[] shorts = ArrayUtilities.Allocate <short>(length); var si = 0; var numerator = (1 << 16) - 1; while (index < length) { shorts[index++] = (short)(numerator * input[si]); si += 4; } var shortOutputNativeArray = new NativeArray <byte>(ArrayUtilities.Cast <byte>(shorts), Allocator.Persistent); request.InvokeCallback(ArrayUtilities.Cast <byte>(shorts)); break; case 4: float[] floats = ArrayUtilities.Allocate <float>(length); var fi = 0; while (index < length) { floats[index++] = input[fi]; fi += 4; } var floatOutputNativeArray = new NativeArray <byte>(ArrayUtilities.Cast <byte>(floats), Allocator.Persistent); request.InvokeCallback(ArrayUtilities.Cast <byte>(floats)); break; default: throw new NotSupportedException(); } } _requestsPool.Enqueue(request); } }