static void WriteRawFloat4Packed(RawTexture dest, float f0, float f1, float f2, float f3, int destX, int destY) { byte r = (byte)(f0 * 255.0f + 0.5f); byte g = (byte)(f1 * 255.0f + 0.5f); byte b = (byte)(f2 * 255.0f + 0.5f); byte a = (byte)(f3 * 255.0f + 0.5f); int offset = destY * dest.Width + destX; dest.Rgba[offset] = new Color32(r, g, b, a); }
internal static void WriteRawInt2Packed(RawTexture dest, int v0, int v1, int destX, int destY) { byte r = (byte)(v0 / 255); byte g = (byte)(v0 - r * 255); byte b = (byte)(v1 / 255); byte a = (byte)(v1 - b * 255); int offset = destY * dest.Width + destX; dest.Rgba[offset] = new Color32(r, g, b, a); }
public void Reset() { if (disposed) { DisposeHelper.NotifyDisposedUsed(this); return; } m_Allocator = new BestFitAllocator((uint)m_Length); UIRUtility.Destroy(m_Atlas); m_RawAtlas = new RawTexture(); MustCommit = false; }
private BitmapSource DecodeTexture(RawTexture model) { BitmapSource bmp; switch (model.Format) { default: case RawTexture.DataFormat.Invalid: { return(null); } case RawTexture.DataFormat.Bgr888: case RawTexture.DataFormat.Bgr565: { var rgb888 = model.Decode(); bmp = BitmapSource.Create(model.Width, model.Height, 96, 96, PixelFormats.Bgr24, null, rgb888, model.Width * 3); break; } case RawTexture.DataFormat.A8: { var rgb888 = model.Decode(); var alpha = GscToAlpha(rgb888); bmp = BitmapSource.Create(model.Width, model.Height, 96, 96, PixelFormats.Bgra32, null, alpha, model.Width * 4); break; } } bmp.Freeze(); return(bmp); }
private void reloadTexture() { var texture = new Texture(textureWidth, 1); //initialise background var raw = new RawTexture(textureWidth, 1); var bytes = raw.Data; const float aa_portion = 0.02f; const float border_portion = 0.128f; const float gradient_portion = 1 - border_portion; const float opacity_at_centre = 0.3f; const float opacity_at_edge = 0.8f; for (int i = 0; i < textureWidth; i++) { float progress = (float)i / (textureWidth - 1); if (progress <= border_portion) { bytes[i * 4] = (byte)(BorderColour.R * 255); bytes[i * 4 + 1] = (byte)(BorderColour.G * 255); bytes[i * 4 + 2] = (byte)(BorderColour.B * 255); bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * (BorderColour.A * 255)); } else { progress -= border_portion; bytes[i * 4] = (byte)(AccentColour.R * 255); bytes[i * 4 + 1] = (byte)(AccentColour.G * 255); bytes[i * 4 + 2] = (byte)(AccentColour.B * 255); bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (AccentColour.A * 255)); } } texture.SetData(new TextureUpload(raw)); path.Texture = texture; container.ForceRedraw(); }
static void BlitRawTexture(RawTexture src, RawTexture dest, int destX, int destY, bool rotate) { if (rotate) { for (int y = 0; y < src.Height; y++) { int srcRowIndex = y * src.Width; int destColumnIndex = destY * dest.Width + destX + y; for (int x = 0; x < src.Width; x++) { int srcIndex = srcRowIndex + x; int destIndex = destColumnIndex + x * dest.Width; dest.Rgba[destIndex] = src.Rgba[srcIndex]; } } } else { for (int y = 0; y < src.Height; y++) { Array.Copy(src.Rgba, y * src.Width, dest.Rgba, (destY + y) * dest.Width + destX, src.Width); } } }
/// <summary>Generates a Texture2D atlas containing the textures and gradients for the vector geometry.</summary> /// <param name="geoms">The list of Geometry objects, probably created with TessellateNodeHierarchy</param> /// <param name="rasterSize">Maximum size of the generated texture</param> /// <returns>The generated texture atlas</returns> public static TextureAtlas GenerateAtlas(IEnumerable <Geometry> geoms, uint rasterSize) { UnityEngine.Profiling.Profiler.BeginSample("GenerateAtlas"); var fills = new Dictionary <IFill, AtlasEntry>(); int texturedGeomCount = 0; foreach (var g in geoms) { RawTexture tex; if (g.Fill is GradientFill) { tex = new RawTexture() { Width = (int)rasterSize, Height = 1, Rgba = RasterizeGradientStripe((GradientFill)g.Fill, (int)rasterSize) }; ++texturedGeomCount; } else if (g.Fill is TextureFill) { var fillTex = ((TextureFill)g.Fill).Texture; tex = new RawTexture() { Rgba = fillTex.GetPixels32(), Width = fillTex.width, Height = fillTex.height }; ++texturedGeomCount; } else { continue; } fills[g.Fill] = new AtlasEntry() { Texture = tex }; } if (fills.Count == 0) { return(null); } Vector2 atlasSize; var rectsToPack = fills.Select(x => new KeyValuePair <IFill, Vector2>(x.Key, new Vector2(x.Value.Texture.Width, x.Value.Texture.Height))).ToList(); rectsToPack.Add(new KeyValuePair <IFill, Vector2>(null, new Vector2(2, 2))); // White fill var pack = PackRects(rectsToPack, out atlasSize); // The first row of the atlas is reserved for the gradient settings for (int packIndex = 0; packIndex < pack.Count; ++packIndex) { var item = pack[packIndex]; item.Position.y += 1; pack[packIndex] = item; } atlasSize.y += 1; // Need enough space on first row for texture settings int maxSettingIndex = 0; foreach (var item in pack) { maxSettingIndex = Math.Max(maxSettingIndex, item.SettingIndex); } int minWidth = (maxSettingIndex + 1) * 3; atlasSize.x = Math.Max(minWidth, (int)atlasSize.x); int atlasWidth = NextPOT((int)atlasSize.x); int atlasHeight = NextPOT((int)atlasSize.y); var atlasColors = new Color32[atlasWidth * atlasHeight]; for (int k = 0; k < atlasWidth * atlasHeight; ++k) { atlasColors[k] = Color.black; } Vector2 atlasInvSize = new Vector2(1.0f / (float)atlasWidth, 1.0f / (float)atlasHeight); Vector2 whiteTexelsScreenPos = pack[pack.Count - 1].Position; int i = 0; RawTexture rawAtlasTex = new RawTexture() { Rgba = atlasColors, Width = atlasWidth, Height = atlasHeight }; foreach (var entry in fills.Values) { var packItem = pack[i++]; entry.AtlasLocation = packItem; BlitRawTexture(entry.Texture, rawAtlasTex, (int)packItem.Position.x, (int)packItem.Position.y, packItem.Rotated); } RawTexture whiteTex = new RawTexture() { Width = 2, Height = 2, Rgba = new Color32[4] }; for (i = 0; i < whiteTex.Rgba.Length; i++) { whiteTex.Rgba[i] = new Color32(0xFF, 0xFF, 0xFF, 0xFF); } BlitRawTexture(whiteTex, rawAtlasTex, (int)whiteTexelsScreenPos.x, (int)whiteTexelsScreenPos.y, false); // Setting 0 is reserved for the white texel WriteRawFloat4Packed(rawAtlasTex, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0); WriteRawInt2Packed(rawAtlasTex, (int)whiteTexelsScreenPos.x + 1, (int)whiteTexelsScreenPos.y + 1, 1, 0); WriteRawInt2Packed(rawAtlasTex, 0, 0, 2, 0); var writtenSettings = new HashSet <int>(); writtenSettings.Add(0); foreach (var g in geoms) { AtlasEntry entry; int vertsCount = g.Vertices.Length; if ((g.Fill != null) && fills.TryGetValue(g.Fill, out entry)) { int setting = entry.AtlasLocation.SettingIndex; if (writtenSettings.Contains(setting)) { continue; } writtenSettings.Add(setting); // There are 3 consecutive pixels to store the settings int destX = setting * 3; var gradientFill = g.Fill as GradientFill; if (gradientFill != null) { var focus = gradientFill.RadialFocus; focus += Vector2.one; focus /= 2.0f; focus.y = 1.0f - focus.y; WriteRawFloat4Packed(rawAtlasTex, ((float)gradientFill.Type) / 255, ((float)gradientFill.Addressing) / 255, focus.x, focus.y, destX++, 0); } var textureFill = g.Fill as TextureFill; if (textureFill != null) { WriteRawFloat4Packed(rawAtlasTex, 0.0f, ((float)textureFill.Addressing) / 255, 0.0f, 0.0f, destX++, 0); } var pos = entry.AtlasLocation.Position; var size = new Vector2(entry.Texture.Width - 1, entry.Texture.Height - 1); WriteRawInt2Packed(rawAtlasTex, (int)pos.x, (int)pos.y, destX++, 0); WriteRawInt2Packed(rawAtlasTex, (int)size.x, (int)size.y, destX++, 0); } } var atlasTex = new Texture2D(atlasWidth, atlasHeight, TextureFormat.ARGB32, false, true); atlasTex.wrapModeU = TextureWrapMode.Clamp; atlasTex.wrapModeV = TextureWrapMode.Clamp; atlasTex.wrapModeW = TextureWrapMode.Clamp; atlasTex.SetPixels32(atlasColors); atlasTex.Apply(); UnityEngine.Profiling.Profiler.EndSample(); return(new TextureAtlas() { Texture = atlasTex, Entries = pack }); }
private static void EncodeSettings(IEnumerable <Geometry> geoms, Dictionary <IFill, AtlasEntry> fills, RawTexture rawAtlasTex, Vector2 whiteTexelsScreenPos) { // Setting 0 is reserved for the white texel WriteRawFloat4Packed(rawAtlasTex, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0); WriteRawInt2Packed(rawAtlasTex, (int)whiteTexelsScreenPos.x + 1, (int)whiteTexelsScreenPos.y + 1, 1, 0); WriteRawInt2Packed(rawAtlasTex, 0, 0, 2, 0); var writtenSettings = new HashSet <int>(); writtenSettings.Add(0); foreach (var g in geoms) { AtlasEntry entry; int vertsCount = g.Vertices.Length; if ((g.Fill != null) && fills.TryGetValue(g.Fill, out entry)) { int setting = entry.AtlasLocation.SettingIndex; if (writtenSettings.Contains(setting)) { continue; } writtenSettings.Add(setting); // There are 3 consecutive pixels to store the settings int destX = 0; int destY = setting; var gradientFill = g.Fill as GradientFill; if (gradientFill != null) { var focus = gradientFill.RadialFocus; focus += Vector2.one; focus /= 2.0f; focus.y = 1.0f - focus.y; WriteRawFloat4Packed(rawAtlasTex, ((float)gradientFill.Type) / 255, ((float)gradientFill.Addressing) / 255, focus.x, focus.y, destX++, destY); } var textureFill = g.Fill as TextureFill; if (textureFill != null) { WriteRawFloat4Packed(rawAtlasTex, 0.0f, ((float)textureFill.Addressing) / 255, 0.0f, 0.0f, destX++, destY); } var pos = entry.AtlasLocation.Position; var size = new Vector2(entry.Texture.Width - 1, entry.Texture.Height - 1); WriteRawInt2Packed(rawAtlasTex, (int)pos.x, (int)pos.y, destX++, destY); WriteRawInt2Packed(rawAtlasTex, (int)size.x, (int)size.y, destX++, destY); } } }
/// <summary>Generates a Texture2D atlas containing the textures and gradients for the vector geometry.</summary> /// <param name="geoms">The list of Geometry objects, probably created with TessellateNodeHierarchy</param> /// <param name="rasterSize">Maximum size of the generated texture</param> /// <param name="generatePOTTexture">Resize the texture to the next power-of-two</param> /// <param name="encodeSettings">Encode the gradient settings inside the texture</param> /// <returns>The generated texture atlas</returns> public static TextureAtlas GenerateAtlas(IEnumerable <Geometry> geoms, uint rasterSize, bool generatePOTTexture = true, bool encodeSettings = true) { var fills = new Dictionary <IFill, AtlasEntry>(); int texturedGeomCount = 0; foreach (var g in geoms) { RawTexture tex; if (g.Fill is GradientFill) { tex = new RawTexture() { Width = (int)rasterSize, Height = 1, Rgba = RasterizeGradientStripe((GradientFill)g.Fill, (int)rasterSize) }; ++texturedGeomCount; } else if (g.Fill is TextureFill) { var fillTex = ((TextureFill)g.Fill).Texture; tex = new RawTexture() { Rgba = fillTex.GetPixels32(), Width = fillTex.width, Height = fillTex.height }; ++texturedGeomCount; } else { continue; } fills[g.Fill] = new AtlasEntry() { Texture = tex }; } if (fills.Count == 0) { return(null); } UnityEngine.Profiling.Profiler.BeginSample("GenerateAtlas"); Vector2 atlasSize; var rectsToPack = fills.Select(x => new KeyValuePair <IFill, Vector2>(x.Key, new Vector2(x.Value.Texture.Width, x.Value.Texture.Height))).ToList(); rectsToPack.Add(new KeyValuePair <IFill, Vector2>(null, new Vector2(2, 2))); // White fill var pack = PackRects(rectsToPack, out atlasSize); if (encodeSettings) { // The first row/cols of the atlas is reserved for the gradient settings for (int packIndex = 0; packIndex < pack.Count; ++packIndex) { var item = pack[packIndex]; item.Position.x += 3; pack[packIndex] = item; } atlasSize.x += 3; } // Need enough space on first 3 columns for texture settings int maxSettingIndex = 0; foreach (var item in pack) { maxSettingIndex = Math.Max(maxSettingIndex, item.SettingIndex); } int minWidth = encodeSettings ? 3 : 0; int minHeight = encodeSettings ? (maxSettingIndex + 1) : maxSettingIndex; atlasSize.x = Math.Max(minWidth, (int)atlasSize.x); atlasSize.y = Math.Max(minHeight, (int)atlasSize.y); int atlasWidth = (int)atlasSize.x; int atlasHeight = (int)atlasSize.y; if (generatePOTTexture) { atlasWidth = NextPOT(atlasWidth); atlasHeight = NextPOT(atlasHeight); } var atlasColors = new Color32[atlasWidth * atlasHeight]; for (int k = 0; k < atlasWidth * atlasHeight; ++k) { atlasColors[k] = Color.black; } Vector2 atlasInvSize = new Vector2(1.0f / (float)atlasWidth, 1.0f / (float)atlasHeight); Vector2 whiteTexelsScreenPos = pack[pack.Count - 1].Position; int i = 0; RawTexture rawAtlasTex = new RawTexture() { Rgba = atlasColors, Width = atlasWidth, Height = atlasHeight }; foreach (var entry in fills.Values) { var packItem = pack[i++]; entry.AtlasLocation = packItem; BlitRawTexture(entry.Texture, rawAtlasTex, (int)packItem.Position.x, (int)packItem.Position.y, packItem.Rotated); } RawTexture whiteTex = new RawTexture() { Width = 2, Height = 2, Rgba = new Color32[4] }; for (i = 0; i < whiteTex.Rgba.Length; i++) { whiteTex.Rgba[i] = new Color32(0xFF, 0xFF, 0xFF, 0xFF); } BlitRawTexture(whiteTex, rawAtlasTex, (int)whiteTexelsScreenPos.x, (int)whiteTexelsScreenPos.y, false); if (encodeSettings) { EncodeSettings(geoms, fills, rawAtlasTex, whiteTexelsScreenPos); } var atlasTex = new Texture2D(atlasWidth, atlasHeight, TextureFormat.ARGB32, false, true); atlasTex.wrapModeU = TextureWrapMode.Clamp; atlasTex.wrapModeV = TextureWrapMode.Clamp; atlasTex.wrapModeW = TextureWrapMode.Clamp; atlasTex.SetPixels32(atlasColors); atlasTex.Apply(false, true); UnityEngine.Profiling.Profiler.EndSample(); return(new TextureAtlas() { Texture = atlasTex, Entries = pack }); }
protected SMDH(bool inter) { AppTitles = new AppTitle[16]; SmallIcon = new RawTexture(24, 24, RawTexture.DataFormat.Bgr565); LargeIcon = new RawTexture(48, 48, RawTexture.DataFormat.Bgr565); }
public void Write(Alloc alloc, GradientSettings[] settings, GradientRemap remap) { if (disposed) { DisposeHelper.NotifyDisposedUsed(this); return; } if (m_RawAtlas.rgba == null) { m_RawAtlas = new RawTexture { rgba = new Color32[m_ElemWidth * m_Length], width = m_ElemWidth, height = m_Length }; int size = m_ElemWidth * m_Length; for (int i = 0; i < size; ++i) { m_RawAtlas.rgba[i] = Color.black; } } s_MarkerWrite.Begin(); int destY = (int)alloc.start; for (int i = 0, settingsCount = settings.Length; i < settingsCount; ++i) { int destX = 0; GradientSettings entry = settings[i]; Debug.Assert(remap == null || destY == remap.destIndex); if (entry.gradientType == GradientType.Radial) { var focus = entry.radialFocus; focus += Vector2.one; focus /= 2.0f; focus.y = 1.0f - focus.y; m_RawAtlas.WriteRawFloat4Packed((float)GradientType.Radial / 255, (float)entry.addressMode / 255, focus.x, focus.y, destX++, destY); } else if (entry.gradientType == GradientType.Linear) { m_RawAtlas.WriteRawFloat4Packed(0.0f, (float)entry.addressMode / 255, 0.0f, 0.0f, destX++, destY); } Vector2Int pos = new Vector2Int(entry.location.x, entry.location.y); var size = new Vector2(entry.location.width - 1, entry.location.height - 1); if (remap != null) { pos = new Vector2Int(remap.location.x, remap.location.y); size = new Vector2(remap.location.width - 1, remap.location.height - 1); } m_RawAtlas.WriteRawInt2Packed(pos.x, pos.y, destX++, destY); m_RawAtlas.WriteRawInt2Packed((int)size.x, (int)size.y, destX++, destY); remap = remap?.next; ++destY; } MustCommit = true; s_MarkerWrite.End(); }
/// <summary> /// Create an upload from a <see cref="RawTexture"/>. This is the preferred method. /// </summary> /// <param name="texture">The texture to upload.</param> public TextureUpload(RawTexture texture) { this.texture = texture; Data = texture.Data; }
public TextureViewModel(RawTexture model, string tag) : base(model, tag) { }