-
-
Save stelabouras/1bf80b252044db7974c57dd6dabee9af to your computer and use it in GitHub Desktop.
CPU-Based Edge Detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEditor; | |
using UnityEngine; | |
namespace Editor.Utility | |
{ | |
public static class EdgeMapUtils | |
{ | |
public const int EDGE_SIZE = 2; | |
public static void Update(IEnumerable<Sprite> spr) | |
{ | |
foreach (var s in spr) | |
Update(s); | |
} | |
private static void Update(Sprite s) | |
{ | |
//aaahaha, ok, oh boy. Yeah, scan the sprite on the cpu, look for edges and plug those into a texture | |
//make sprite readable | |
var test = s.texture; | |
var path = AssetDatabase.GetAssetPath(s); | |
var spriteTi = (TextureImporter)TextureImporter.GetAtPath(path); | |
spriteTi.isReadable = true; | |
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); | |
//DO STUFF | |
var edges = BuildEdgeTexture(s); | |
var savedEdgePath = SaveEdges(s, path, edges); | |
//link it to sprite as a secondary map | |
SpriteUtils.TryAddSecondaryTexture(spriteTi, "_EdgeMap", savedEdgePath); | |
//put sprite back the way it was. | |
spriteTi.isReadable = false; | |
} | |
private static string SaveEdges(Sprite s, string path, Texture2D edges) | |
{ | |
var folder = path.Remove(path.LastIndexOf(s.name) - 1); | |
EditorUtils.LazyCreateFolder(folder, "EdgeMaps"); | |
var edgePath = $"{folder}/EdgeMaps/{s.name}_edges.png"; | |
var bytes = edges.EncodeToPNG(); | |
System.IO.File.WriteAllBytes(edgePath, bytes); | |
AssetDatabase.ImportAsset(edgePath, ImportAssetOptions.ForceSynchronousImport); | |
//AssetDatabase.CreateAsset(edges, edgePath); | |
var ti = AssetImporter.GetAtPath(edgePath) as TextureImporter; | |
ti.textureType = TextureImporterType.Sprite; | |
ti.filterMode = FilterMode.Point; | |
ti.textureCompression = TextureImporterCompression.Uncompressed; | |
ti.mipmapEnabled = false; | |
ti.alphaIsTransparency = false; | |
EditorUtility.SetDirty(ti); | |
ti.SaveAndReimport(); | |
return edgePath; | |
} | |
private static Texture2D BuildEdgeTexture(Sprite s) | |
{ | |
var edges = new Texture2D(s.texture.width, s.texture.height, TextureFormat.RGBA32, false); | |
for (int x = 0; x < s.texture.width; x++) | |
{ | |
for (int y = 0; y < s.texture.height; y++) | |
{ | |
edges.SetPixel(x, y, GetEdge(s, x, y)); | |
} | |
} | |
edges.Apply(); | |
return edges; | |
} | |
//encodes edge information into 1 channel of the texture | |
private static Color GetEdge(Sprite s, int x, int y) | |
{ | |
//MY COUNTERPART IS CustomRenderGraphBlock.hlsl.getSpriteEdges_float | |
var col = new Color(0, 0, 0, 0); | |
var px = s.texture.GetPixel(x, y); | |
if (px.a < 1) | |
{ | |
return col; | |
} | |
else | |
{ | |
for (int edgeTest = EDGE_SIZE; edgeTest >= 0; edgeTest--) | |
{ | |
float edgeAlpha = 1f - (float)edgeTest / ((float)EDGE_SIZE + 1f); | |
//test up | |
if (IsEdge(s, x, y + edgeTest)) | |
col.r = edgeAlpha; | |
//test right | |
if (IsEdge(s, x + edgeTest, y)) | |
col.g = edgeAlpha; | |
//test left | |
if (IsEdge(s, x - edgeTest, y)) | |
col.b = edgeAlpha; | |
//test bot | |
if (IsEdge(s, x, y - edgeTest)) | |
col.a = edgeAlpha; | |
} | |
} | |
return col; | |
} | |
private static bool IsEdge(Sprite s, int x, int y) | |
{ | |
if (x < 0 || y < 0 || x >= s.texture.width || y >= s.texture.height) | |
return true; | |
else return s.texture.GetPixel(x, y).a == 0f; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment