├── .gitignore
├── CHANGELOG.md
├── CHANGELOG.md.meta
├── Editor.meta
├── Editor
├── Philira.SmartTexture.Editor.asmdef
├── Philira.SmartTexture.Editor.asmdef.meta
├── SmartTextureImporter.cs
├── SmartTextureImporter.cs.meta
├── SmartTextureImporterEditor.cs
└── SmartTextureImporterEditor.cs.meta
├── LICENSE
├── LICENSE.meta
├── README.md
├── README.md.meta
├── Resources.meta
├── Resources
├── PackChannel.compute
└── PackChannel.compute.meta
├── Runtime.meta
├── Runtime
├── Philira.SmartTexture.Runtime.asmdef
├── Philira.SmartTexture.Runtime.asmdef.meta
├── TextureChannelPacker.cs
└── TextureChannelPacker.cs.meta
├── Shaders.meta
├── Shaders
├── PackShader.shader
└── PackShader.shader.meta
├── Tests.meta
├── Tests
├── Editor.meta
└── Editor
│ ├── Philira.SmartTexture.Editor.Tests.asmdef
│ └── Philira.SmartTexture.Editor.Tests.asmdef.meta
├── package.json
└── package.json.meta
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vscode/
2 |
3 | # Visual Studio cache directory
4 | .vs/
5 |
6 | # Autogenerated VS/MD/Consulo solution and project files
7 | ExportedObj/
8 | .consulo/
9 | *.csproj
10 | *.unityproj
11 | *.sln
12 | *.suo
13 | *.tmp
14 | *.user
15 | *.userprefs
16 | *.pidb
17 | *.booproj
18 | *.svd
19 | *.pdb
20 | *.mdb
21 | *.opendb
22 | *.VC.db
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this package are documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 | ## [0.1.0] - 2020-05-16
9 |
10 | ### Added
11 |
12 | - Packing tool that supports GPU and CPU channel packing.
--------------------------------------------------------------------------------
/CHANGELOG.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 79a1701d9970e4645b016ab2b257cd19
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e84552be309687144a83f2502a9eaf7d
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/Philira.SmartTexture.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Phillira.SmartTexture.Editor",
3 | "references": [
4 | "Philira.SmartTexture.Runtime"
5 | ],
6 | "optionalUnityReferences": [],
7 | "includePlatforms": [
8 | "Editor"
9 | ],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false,
12 | "overrideReferences": true,
13 | "precompiledReferences": [],
14 | "autoReferenced": false,
15 | "defineConstraints": []
16 | }
--------------------------------------------------------------------------------
/Editor/Philira.SmartTexture.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 447a42f34d7589946b8de01d4e806a77
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor/SmartTextureImporter.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using UnityEditor;
3 | #if UNITY_2020_1_OR_NEWER
4 | using UnityEditor.AssetImporters;
5 | #else
6 | using UnityEditor.Experimental.AssetImporters;
7 | #endif
8 | using UnityEngine;
9 | using UnityEngine.Experimental.Rendering;
10 | using Object = UnityEngine.Object;
11 |
12 | namespace SmartTexture
13 | {
14 | [ScriptedImporter(k_SmartTextureVersion, k_SmartTextureExtesion)]
15 | public class SmartTextureImporter : ScriptedImporter
16 | {
17 | public const string k_SmartTextureExtesion = "smartex";
18 | public const int k_SmartTextureVersion = 1;
19 | public const int k_MenuPriority = 320;
20 |
21 | // Input Texture Settings
22 | [SerializeField] Texture2D[] m_InputTextures = new Texture2D[4];
23 |
24 | [SerializeField] TexturePackingSettings[] m_InputTextureSettings = new TexturePackingSettings[4]
25 | {
26 | new TexturePackingSettings {remapRange = new Vector2(0.0f, 1.0f)},
27 | new TexturePackingSettings {remapRange = new Vector2(0.0f, 1.0f)},
28 | new TexturePackingSettings {remapRange = new Vector2(0.0f, 1.0f)},
29 | new TexturePackingSettings {remapRange = new Vector2(0.0f, 1.0f)},
30 | };
31 |
32 | // Output Texture Settings
33 | [SerializeField] bool m_IsReadable = false;
34 | [SerializeField] bool m_sRGBTexture = false;
35 | [SerializeField] bool m_EnableMipMap = true;
36 | [SerializeField] bool m_StreamingMipMaps = false;
37 | [SerializeField] int m_StreamingMipMapPriority = 0;
38 |
39 | // TODO: MipMap Generation, is it possible to configure?
40 | //[SerializeField] bool m_BorderMipMaps = false;
41 | //[SerializeField] TextureImporterMipFilter m_MipMapFilter = TextureImporterMipFilter.BoxFilter;
42 | //[SerializeField] bool m_MipMapsPreserveCoverage = false;
43 | //[SerializeField] bool m_FadeoutMipMaps = false;
44 |
45 | [SerializeField] FilterMode m_FilterMode = FilterMode.Bilinear;
46 | [SerializeField] TextureWrapMode m_WrapMode = TextureWrapMode.Repeat;
47 | [SerializeField] int m_AnisotropicLevel = 1;
48 |
49 | [SerializeField]
50 | TextureImporterPlatformSettings m_TexturePlatformSettings = new TextureImporterPlatformSettings();
51 |
52 | [SerializeField] TextureFormat m_TextureFormat = TextureFormat.RGBA32;
53 | [SerializeField] bool m_UseExplicitTextureFormat = false;
54 |
55 | [MenuItem("Assets/Create/Smart Texture", priority = k_MenuPriority)]
56 | static void CreateSmartTextureMenuItem()
57 | {
58 | // Asset creation code from pschraut Texture2DArrayImporter
59 | // https://github.com/pschraut/UnityTexture2DArrayImportPipeline/blob/master/Editor/Texture2DArrayImporter.cs#L360-L383
60 | string directoryPath = "Assets";
61 | foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
62 | {
63 | directoryPath = AssetDatabase.GetAssetPath(obj);
64 | if (!string.IsNullOrEmpty(directoryPath) && File.Exists(directoryPath))
65 | {
66 | directoryPath = Path.GetDirectoryName(directoryPath);
67 | break;
68 | }
69 | }
70 |
71 | directoryPath = directoryPath.Replace("\\", "/");
72 | if (directoryPath.Length > 0 && directoryPath[directoryPath.Length - 1] != '/')
73 | directoryPath += "/";
74 | if (string.IsNullOrEmpty(directoryPath))
75 | directoryPath = "Assets/";
76 |
77 | var fileName = string.Format("SmartTexture.{0}", k_SmartTextureExtesion);
78 | directoryPath = AssetDatabase.GenerateUniqueAssetPath(directoryPath + fileName);
79 | ProjectWindowUtil.CreateAssetWithContent(directoryPath,
80 | "Smart Texture Asset for Unity. Allows to channel pack textures by using a ScriptedImporter. Requires Smart Texture Package from https://github.com/phi-lira/SmartTexture. Developed by Felipe Lira.");
81 | }
82 |
83 |
84 | public override void OnImportAsset(AssetImportContext ctx)
85 | {
86 | int width = m_TexturePlatformSettings.maxTextureSize;
87 | int height = m_TexturePlatformSettings.maxTextureSize;
88 | Texture2D[] textures = m_InputTextures;
89 | TexturePackingSettings[] settings = m_InputTextureSettings;
90 |
91 | bool canGenerateTexture = GetOuputTextureSize(textures, out var inputW, out var inputH);
92 | bool error = false;
93 |
94 | //Mimic default importer. We use max size unless assets are smaller
95 | width = width < inputW ? width : inputW;
96 | height = height < inputH ? height : inputH;
97 |
98 | TextureFormat textureFormat = m_UseExplicitTextureFormat ? m_TextureFormat : TextureFormat.RGBA32;
99 | if (!SystemInfo.SupportsTextureFormat(m_TextureFormat))
100 | textureFormat = TextureFormat.RGBA32;
101 |
102 | GraphicsFormat graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(textureFormat, m_sRGBTexture);
103 | if (graphicsFormat == GraphicsFormat.None)
104 | {
105 | graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(TextureFormat.RGBA32, m_sRGBTexture);
106 | error = true;
107 | }
108 |
109 | TextureCreationFlags textureCreationFlags = TextureCreationFlags.None;
110 | if (m_EnableMipMap)
111 | textureCreationFlags |= TextureCreationFlags.MipChain;
112 | if (m_TexturePlatformSettings.crunchedCompression)
113 | textureCreationFlags |= TextureCreationFlags.Crunch;
114 |
115 | Texture2D texture = new Texture2D(width, height, graphicsFormat, textureCreationFlags)
116 | {
117 | filterMode = m_FilterMode,
118 | wrapMode = m_WrapMode,
119 | anisoLevel = m_AnisotropicLevel,
120 | };
121 |
122 | if (!texture)
123 | {
124 | canGenerateTexture = false;
125 | error = true;
126 | }
127 |
128 | if (canGenerateTexture)
129 | {
130 | //Only attempt to apply any settings if the inputs exist
131 | texture.PackChannels(textures, settings, graphicsFormat, m_sRGBTexture, m_EnableMipMap);
132 |
133 | // Mark all input textures as dependency to the texture array.
134 | // This causes the texture array to get re-generated when any input texture changes or when the build target changed.
135 | foreach (Texture2D t in textures)
136 | {
137 | if (t != null)
138 | {
139 | var path = AssetDatabase.GetAssetPath(t);
140 | ctx.DependsOnSourceAsset(path);
141 | }
142 | }
143 |
144 | // TODO: Seems like we need to call TextureImporter.SetPlatformTextureSettings to register/apply platform
145 | // settings. However we can't subclass from TextureImporter... Is there other way?
146 |
147 | //Currently just supporting one compression format in liew of TextureImporter.SetPlatformTextureSettings
148 | if (m_UseExplicitTextureFormat)
149 | EditorUtility.CompressTexture(texture, textureFormat, 100);
150 | else if (m_TexturePlatformSettings.textureCompression != TextureImporterCompression.Uncompressed)
151 | texture.Compress(m_TexturePlatformSettings.textureCompression ==
152 | TextureImporterCompression.CompressedHQ);
153 |
154 | // Not applying for now, seems to cause problems during import...
155 | // ApplyPropertiesViaSerializedObj(texture);
156 |
157 | texture.Apply(m_EnableMipMap, !m_IsReadable);
158 | }
159 |
160 | if (texture)
161 | {
162 | ctx.AddObjectToAsset("mask", texture, texture);
163 | ctx.SetMainObject(texture);
164 | }
165 |
166 | if (error)
167 | {
168 | Debug.LogError($"MaskTexture ({name}): Error creating texture with format {graphicsFormat}.");
169 | }
170 | }
171 |
172 | void ApplyPropertiesViaSerializedObj(Texture tex)
173 | {
174 | var so = new SerializedObject(tex);
175 |
176 | so.FindProperty("m_IsReadable").boolValue = m_IsReadable;
177 | so.FindProperty("m_StreamingMipmaps").boolValue = m_StreamingMipMaps;
178 | so.FindProperty("m_StreamingMipmapsPriority").intValue = m_StreamingMipMapPriority;
179 | //Set ColorSpace on ctr instead
180 | //so.FindProperty("m_ColorSpace").intValue = (int)(m_sRGBTexture ? ColorSpace.Gamma : ColorSpace.Linear);
181 | so.ApplyModifiedPropertiesWithoutUndo();
182 | }
183 |
184 | static bool GetOuputTextureSize(Texture2D[] textures, out int width, out int height)
185 | {
186 | Texture2D masterTexture = null;
187 | foreach (Texture2D t in textures)
188 | {
189 | if (t != null)
190 | {
191 | //Previously we only read the first readable asset
192 | //but we can get the width&height of unreadable textures.
193 | //May need more complex selection as now Red channel dictates minimum size
194 | //Should we try and find the smallest?
195 | masterTexture = t;
196 | break;
197 | }
198 | }
199 |
200 | if (masterTexture == null)
201 | {
202 | var defaultTexture = Texture2D.blackTexture;
203 | width = defaultTexture.width;
204 | height = defaultTexture.height;
205 | return false;
206 | }
207 |
208 | width = masterTexture.width;
209 | height = masterTexture.height;
210 | return true;
211 | }
212 | }
213 | }
--------------------------------------------------------------------------------
/Editor/SmartTextureImporter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b2456aa1653d249e08f78b862a3bd857
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/SmartTextureImporterEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEditor;
3 | #if UNITY_2020_1_OR_NEWER
4 | using UnityEditor.AssetImporters;
5 | #else
6 | using UnityEditor.Experimental.AssetImporters;
7 | #endif
8 | using UnityEngine;
9 | using UnityEngine.Experimental.Rendering;
10 |
11 | namespace SmartTexture
12 | {
13 | [CustomEditor(typeof(SmartTextureImporter), true)]
14 | class SmartTextureImporterEditor : ScriptedImporterEditor
15 | {
16 | internal static class Styles
17 | {
18 | public static readonly GUIContent[] labelChannels =
19 | {
20 | EditorGUIUtility.TrTextContent("Texture",
21 | "This texture source channel will be packed into the Output texture red channel"),
22 | EditorGUIUtility.TrTextContent("Texture",
23 | "This texture source channel will be packed into the Output texture green channel"),
24 | EditorGUIUtility.TrTextContent("Texture",
25 | "This texture source channel will be packed into the Output texture blue channel"),
26 | EditorGUIUtility.TrTextContent("Texture",
27 | "This texture source channel will be packed into the Output texture alpha channel"),
28 | };
29 |
30 | public static readonly GUIContent invertColor =
31 | EditorGUIUtility.TrTextContent("Invert Color", "If enabled outputs the inverted color (1.0 - color)");
32 |
33 | public static readonly GUIContent remapRange =
34 | EditorGUIUtility.TrTextContent("Remap", "Remaps the input texture value");
35 |
36 | public static readonly GUIContent useLuminance = EditorGUIUtility.TrTextContent("Use Luminance",
37 | "If enabled, outputs the combined rgb luminance value.");
38 |
39 | public static readonly GUIContent channel = EditorGUIUtility.TrTextContent("Input Channel",
40 | "Selects the RGBA channel to output, defaults to Red.");
41 |
42 | public static readonly GUIContent readWrite = EditorGUIUtility.TrTextContent("Read/Write Enabled",
43 | "Enable to be able to access the raw pixel data from code.");
44 |
45 | public static readonly GUIContent generateMipMaps = EditorGUIUtility.TrTextContent("Generate Mip Maps");
46 | public static readonly GUIContent streamingMipMaps = EditorGUIUtility.TrTextContent("Streaming Mip Maps");
47 |
48 | public static readonly GUIContent streamingMipMapsPrio =
49 | EditorGUIUtility.TrTextContent("Streaming Mip Maps Priority");
50 |
51 | public static readonly GUIContent sRGBTexture = EditorGUIUtility.TrTextContent("sRGB (Color Texture)",
52 | "Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).");
53 |
54 | public static readonly GUIContent format = EditorGUIUtility.TrTextContent("Output Texture Format");
55 |
56 | public static readonly GUIContent textureFilterMode = EditorGUIUtility.TrTextContent("Filter Mode");
57 | public static readonly GUIContent textureWrapMode = EditorGUIUtility.TrTextContent("Wrap Mode");
58 |
59 | public static readonly GUIContent textureAnisotropicLevel =
60 | EditorGUIUtility.TrTextContent("Anisotropic Level");
61 |
62 | public static readonly GUIContent crunchCompression =
63 | EditorGUIUtility.TrTextContent("Use Crunch Compression");
64 |
65 | public static readonly GUIContent useExplicitTextureFormat =
66 | EditorGUIUtility.TrTextContent("Use Explicit Texture Format");
67 |
68 | public static readonly string[] textureSizeOptions =
69 | {
70 | "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192",
71 | };
72 |
73 | public static readonly string[] textureCompressionOptions =
74 | Enum.GetNames(typeof(TextureImporterCompression));
75 |
76 | public static readonly string[] textureFormat = Enum.GetNames(typeof(TextureFormat));
77 | public static readonly string[] resizeAlgorithmOptions = Enum.GetNames(typeof(TextureResizeAlgorithm));
78 | }
79 |
80 | SerializedProperty m_StreamingMipMaps;
81 | SerializedProperty m_StreamingMipMapPriority;
82 | readonly SerializedProperty[] m_InputTextures = new SerializedProperty[4];
83 | readonly SerializedProperty[] m_InputTextureSettings = new SerializedProperty[4];
84 |
85 | SerializedProperty m_IsReadable;
86 | SerializedProperty m_sRGBTexture;
87 |
88 | SerializedProperty m_EnableMipMap;
89 |
90 | SerializedProperty m_FilterMode;
91 | SerializedProperty m_WrapMode;
92 | SerializedProperty m_AnisotropicLevel;
93 |
94 | SerializedProperty m_TexturePlatformSettings;
95 | SerializedProperty m_TextureFormat;
96 | SerializedProperty m_UseExplicitTextureFormat;
97 |
98 | bool m_ShowAdvanced = false;
99 |
100 | const string k_AdvancedTextureSettingName = "SmartTextureImporterShowAdvanced";
101 |
102 | public override void OnEnable()
103 | {
104 | base.OnEnable();
105 | CacheSerializedProperties();
106 | }
107 |
108 | public override void OnInspectorGUI()
109 | {
110 | serializedObject.Update();
111 |
112 | m_ShowAdvanced = EditorPrefs.GetBool(k_AdvancedTextureSettingName, m_ShowAdvanced);
113 |
114 |
115 | EditorGUILayout.Space();
116 |
117 | EditorGUILayout.LabelField("Red Input", EditorStyles.boldLabel);
118 | DrawInputTexture(0);
119 |
120 | var textureFormat = m_UseExplicitTextureFormat.boolValue
121 | ? (TextureFormat) m_TextureFormat.intValue
122 | : TextureFormat.RGBA32;
123 | var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(textureFormat, m_sRGBTexture.boolValue);
124 | var componentCount = GraphicsFormatUtility.GetComponentCount(graphicsFormat);
125 |
126 | if (componentCount >= 2)
127 | {
128 | EditorGUILayout.LabelField("Green Input", EditorStyles.boldLabel);
129 | DrawInputTexture(1);
130 | }
131 |
132 | if (componentCount >= 3)
133 | {
134 | EditorGUILayout.LabelField("Blue Input", EditorStyles.boldLabel);
135 | DrawInputTexture(2);
136 | }
137 |
138 | if (componentCount >= 4)
139 | {
140 | EditorGUILayout.LabelField("Alpha Input", EditorStyles.boldLabel);
141 | DrawInputTexture(3);
142 | }
143 |
144 | EditorGUILayout.Space();
145 | EditorGUILayout.Space();
146 |
147 |
148 | EditorGUILayout.LabelField("Output Texture", EditorStyles.boldLabel);
149 | using (new EditorGUI.IndentLevelScope())
150 | {
151 | EditorGUILayout.PropertyField(m_EnableMipMap, Styles.generateMipMaps);
152 | // EditorGUILayout.PropertyField(m_StreamingMipMaps, Styles.streamingMipMaps);
153 | // EditorGUILayout.PropertyField(m_StreamingMipMapPriority, Styles.streamingMipMapsPrio);
154 | EditorGUILayout.Space();
155 |
156 | EditorGUILayout.PropertyField(m_FilterMode, Styles.textureFilterMode);
157 | EditorGUILayout.PropertyField(m_WrapMode, Styles.textureWrapMode);
158 |
159 | EditorGUILayout.IntSlider(m_AnisotropicLevel, 0, 16, Styles.textureAnisotropicLevel);
160 | EditorGUILayout.Space();
161 |
162 | EditorGUILayout.PropertyField(m_IsReadable, Styles.readWrite);
163 | EditorGUILayout.PropertyField(m_sRGBTexture, Styles.sRGBTexture);
164 | }
165 |
166 | EditorGUILayout.Space();
167 | EditorGUILayout.Space();
168 |
169 | // TODO: Figure out how to apply PlatformTextureImporterSettings on ScriptedImporter
170 | DrawTextureImporterSettings();
171 | EditorGUILayout.Space();
172 | EditorGUILayout.Space();
173 | serializedObject.ApplyModifiedProperties();
174 | ApplyRevertGUI();
175 | }
176 |
177 | void DrawInputTexture(int index)
178 | {
179 | if (index < 0 || index >= 4)
180 | return;
181 |
182 | EditorGUI.indentLevel++;
183 |
184 | EditorGUILayout.PropertyField(m_InputTextures[index], Styles.labelChannels[index]);
185 |
186 | SerializedProperty remapRange = m_InputTextureSettings[index].FindPropertyRelative("remapRange");
187 | DrawMinMaxSlider(remapRange);
188 |
189 | SerializedProperty invertColor = m_InputTextureSettings[index].FindPropertyRelative("invertColor");
190 | invertColor.boolValue = EditorGUILayout.Toggle(Styles.invertColor, invertColor.boolValue);
191 |
192 | SerializedProperty useLuminance = m_InputTextureSettings[index].FindPropertyRelative("useLuminance");
193 | useLuminance.boolValue = EditorGUILayout.Toggle(Styles.useLuminance, useLuminance.boolValue);
194 |
195 | if (!useLuminance.boolValue)
196 | {
197 | SerializedProperty channel = m_InputTextureSettings[index].FindPropertyRelative("channel");
198 | EditorGUILayout.PropertyField(channel, Styles.channel);
199 | }
200 |
201 | EditorGUILayout.Space();
202 |
203 | EditorGUI.indentLevel--;
204 | }
205 |
206 | void DrawTextureImporterSettings()
207 | {
208 | SerializedProperty maxTextureSize = m_TexturePlatformSettings.FindPropertyRelative("m_MaxTextureSize");
209 | SerializedProperty resizeAlgorithm = m_TexturePlatformSettings.FindPropertyRelative("m_ResizeAlgorithm");
210 | SerializedProperty textureCompression =
211 | m_TexturePlatformSettings.FindPropertyRelative("m_TextureCompression");
212 | SerializedProperty textureCompressionCrunched =
213 | m_TexturePlatformSettings.FindPropertyRelative("m_CrunchedCompression");
214 |
215 | EditorGUILayout.LabelField("Texture Platform Settings", EditorStyles.boldLabel);
216 | using (new EditorGUI.IndentLevelScope())
217 | {
218 | EditorGUI.BeginChangeCheck();
219 | int sizeOption = EditorGUILayout.Popup("Texture Size", (int) Mathf.Log(maxTextureSize.intValue, 2) - 5,
220 | Styles.textureSizeOptions);
221 | if (EditorGUI.EndChangeCheck())
222 | maxTextureSize.intValue = 32 << sizeOption;
223 |
224 | EditorGUI.BeginChangeCheck();
225 | int resizeOption = EditorGUILayout.Popup("Resize Algorithm", resizeAlgorithm.intValue,
226 | Styles.resizeAlgorithmOptions);
227 | if (EditorGUI.EndChangeCheck())
228 | resizeAlgorithm.intValue = resizeOption;
229 |
230 | EditorGUILayout.LabelField("Compression", EditorStyles.boldLabel);
231 | using (new EditorGUI.IndentLevelScope())
232 | {
233 | EditorGUI.BeginChangeCheck();
234 | bool explicitFormat = EditorGUILayout.Toggle(Styles.useExplicitTextureFormat,
235 | m_UseExplicitTextureFormat.boolValue);
236 | if (EditorGUI.EndChangeCheck())
237 | m_UseExplicitTextureFormat.boolValue = explicitFormat;
238 |
239 | using (new EditorGUI.DisabledScope(explicitFormat))
240 | {
241 | GUILayout.BeginHorizontal();
242 | EditorGUI.BeginChangeCheck();
243 | int compressionOption = EditorGUILayout.Popup("Texture Type", textureCompression.intValue,
244 | Styles.textureCompressionOptions);
245 | if (EditorGUI.EndChangeCheck())
246 | textureCompression.intValue = compressionOption;
247 |
248 | EditorGUI.BeginChangeCheck();
249 | var oldWidth = EditorGUIUtility.labelWidth;
250 | EditorGUIUtility.labelWidth = 100f;
251 | bool crunchOption = EditorGUILayout.Toggle(Styles.crunchCompression,
252 | textureCompressionCrunched.boolValue);
253 | EditorGUIUtility.labelWidth = oldWidth;
254 | if (EditorGUI.EndChangeCheck())
255 | textureCompressionCrunched.boolValue = crunchOption;
256 | GUILayout.EndHorizontal();
257 | }
258 |
259 | using (new EditorGUI.DisabledScope(!explicitFormat))
260 | {
261 | EditorGUI.BeginChangeCheck();
262 |
263 | int format = EditorGUILayout
264 | .EnumPopup("Texture Format", (TextureFormat) m_TextureFormat.intValue).GetHashCode();
265 |
266 | if (EditorGUI.EndChangeCheck())
267 | {
268 | if (!SystemInfo.SupportsTextureFormat((TextureFormat) format))
269 | EditorGUILayout.HelpBox("Texture format unsupported.", MessageType.Warning, true);
270 |
271 | m_TextureFormat.intValue = format;
272 | }
273 | }
274 | }
275 | }
276 | }
277 |
278 |
279 | void CacheSerializedProperties()
280 | {
281 | SerializedProperty inputTextures = serializedObject.FindProperty("m_InputTextures");
282 | SerializedProperty inputTexturesSettings = serializedObject.FindProperty("m_InputTextureSettings");
283 |
284 | for (int i = 0; i < 4; ++i)
285 | {
286 | m_InputTextures[i] = inputTextures.GetArrayElementAtIndex(i);
287 | m_InputTextureSettings[i] = inputTexturesSettings.GetArrayElementAtIndex(i);
288 | }
289 |
290 | m_IsReadable = serializedObject.FindProperty("m_IsReadable");
291 | m_sRGBTexture = serializedObject.FindProperty("m_sRGBTexture");
292 |
293 | m_EnableMipMap = serializedObject.FindProperty("m_EnableMipMap");
294 | m_StreamingMipMaps = serializedObject.FindProperty("m_StreamingMipMaps");
295 | m_StreamingMipMapPriority = serializedObject.FindProperty("m_StreamingMipMapPriority");
296 |
297 | m_FilterMode = serializedObject.FindProperty("m_FilterMode");
298 | m_WrapMode = serializedObject.FindProperty("m_WrapMode");
299 | m_AnisotropicLevel = serializedObject.FindProperty("m_AnisotropicLevel");
300 |
301 | m_TexturePlatformSettings = serializedObject.FindProperty("m_TexturePlatformSettings");
302 | m_TextureFormat = serializedObject.FindProperty("m_TextureFormat");
303 | m_UseExplicitTextureFormat = serializedObject.FindProperty("m_UseExplicitTextureFormat");
304 | }
305 |
306 | static void DrawMinMaxSlider(SerializedProperty property)
307 | {
308 | using (var horizontal = new EditorGUILayout.HorizontalScope())
309 | {
310 | using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, Styles.remapRange, property))
311 | {
312 | var v = property.vector2Value;
313 |
314 | const int kFloatFieldWidth = 50;
315 | const int kSeparatorWidth = 5;
316 |
317 | float indentOffset = EditorGUI.indentLevel * 15f;
318 | var lineRect = EditorGUILayout.GetControlRect();
319 | var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset,
320 | lineRect.height);
321 | var floatFieldLeft = new Rect(labelRect.xMax, lineRect.y, kFloatFieldWidth + indentOffset,
322 | lineRect.height);
323 | var sliderRect = new Rect(floatFieldLeft.xMax + kSeparatorWidth - indentOffset, lineRect.y,
324 | lineRect.width - labelRect.width - kFloatFieldWidth * 2 - kSeparatorWidth * 2, lineRect.height);
325 | var floatFieldRight = new Rect(sliderRect.xMax + kSeparatorWidth - indentOffset, lineRect.y,
326 | kFloatFieldWidth + indentOffset, lineRect.height);
327 |
328 | EditorGUI.PrefixLabel(labelRect, propertyScope.content);
329 | v.x = EditorGUI.FloatField(floatFieldLeft, v.x);
330 | EditorGUI.MinMaxSlider(sliderRect, ref v.x, ref v.y, 0.0f, 1.0f);
331 | v.y = EditorGUI.FloatField(floatFieldRight, v.y);
332 |
333 | property.vector2Value = v;
334 |
335 | }
336 |
337 | }
338 |
339 | }
340 | }
341 | }
--------------------------------------------------------------------------------
/Editor/SmartTextureImporterEditor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6897efd5ee27b4a3d84c5ee1d2bf4fa0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Felipe Lira
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0b1ef955611321d4c964399689ef1ef7
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SmartTexture Asset for Unity
2 | SmartTexture is a custom asset for Unity that allows you a [channel packing](http://wiki.polycount.com/wiki/ChannelPacking) workflow in the editortextures and use them in the Unity editor for a streamlined workflow.
3 | SmartTextures work as a regular 2D texture asset and you can assign it to material inspectors.
4 |
5 | Dependency tracking is handled by SmartTexture, that means you can change input textures and the texture asset will be re-generated. The input textures are editor only dependencies, they will not be included in the build, unless they are referenced by another asset or scene.
6 |
7 |
8 |
9 | ---
10 | **NOTE**
11 |
12 | This package is still a Proof of Concept (POC) and it's still experimental.
13 | You can request features or submit bugs by creating new issues in the issue tab. For feature request please add "enhancement" label.
14 |
15 | ---
16 |
17 |
18 | ## Installation
19 | SmartTexture is a unity package and you can install it from Package Manager.
20 |
21 | Option 1: [Install package via Github](https://docs.unity3d.com/Manual/upm-ui-giturl.html).
22 |
23 | Option 2: Clone or download this Github project and [install it as a local package](https://docs.unity3d.com/Manual/upm-ui-local.html).
24 |
25 | ## How to use
26 | 1) Create a SmartTexture asset by clicking on `Asset -> Create -> Smart Texture`, or by right-clicking on the Project Window and then `Create -> Smart Texture`.
27 |
28 |
29 | 2) An asset will be created in your project.
30 |
31 |
32 | 3) On the asset inspector you can configure input textures and texture settings for your smart texture.
33 | 4) Hit `Apply` button to generate the texture with selected settings.
34 |
35 |
36 | 5) Now you can use this texture as any regular 2D texture in your project.
37 |
38 |
39 | ## Acknowledgements
40 | * Thanks to pschraut for [Texture2DArrayImporter](https://github.com/pschraut/UnityTexture2DArrayImportPipeline) project. I've used that project to learn a few things about ScriptedImporter and reused the code to create asset file.
41 | * Thanks to [Aras P.](https://twitter.com/aras_p) for guidance and ideas on how to create this.
42 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 348769316597fe54b9db2cd435d11a02
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Resources.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e0298833e2c50e14fa9e8e2f3f06ce58
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Resources/PackChannel.compute:
--------------------------------------------------------------------------------
1 | //
2 |
3 | Texture2D _RedMap;
4 | Texture2D _GreenMap;
5 | Texture2D _BlueMap;
6 | Texture2D _AlphaMap;
7 |
8 | float4 _RedChannelParams;
9 | float4 _GreenChannelParams;
10 | float4 _BlueChannelParams;
11 | float4 _AlphaChannelParams;
12 |
13 | RWTexture2D _Output;
14 | float4 _OutputSize;
15 |
16 | sampler sampler_point_clamp;
17 |
18 | float MapSourceToChannel(float4 source, float channelOrParam, float2 remap)
19 | {
20 | // Invert?
21 | if (channelOrParam < 0)
22 | {
23 | channelOrParam = -channelOrParam; // reset
24 | source = float4(1, 1, 1, 1) - source;
25 | }
26 |
27 | float output;
28 |
29 | // Use luminance?
30 | if (channelOrParam >= 5)
31 | output = source.r * 0.3 + source.g * 0.59 + source.b * 0.11; // Photoshop desaturation : G*.59+R*.3+B*.11
32 | else
33 | output = source[channelOrParam-1];
34 |
35 | return output * (remap.y - remap.x) + remap.x;
36 | }
37 |
38 | #pragma kernel PackChannelsCS THREADGROUP_SIZE=8
39 | [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, 1)]
40 | void PackChannelsCS(uint2 id : SV_DispatchThreadID)
41 | {
42 | const uint2 size = (uint2)_OutputSize.xy;
43 | if (id.x >= size.x || id.y >= size.y)
44 | return;
45 |
46 | float2 sv = id + 0.5;
47 | float2 uv = sv * _OutputSize.zw;
48 |
49 | float4 color = float4(0, 0, 0, 0);
50 | color.r = MapSourceToChannel(_RedMap.SampleLevel(sampler_point_clamp, uv, 0), _RedChannelParams.x, _RedChannelParams.yz);
51 | color.g = MapSourceToChannel(_GreenMap.SampleLevel(sampler_point_clamp, uv, 0), _GreenChannelParams.x, _GreenChannelParams.yz);
52 | color.b = MapSourceToChannel(_BlueMap.SampleLevel(sampler_point_clamp, uv, 0), _BlueChannelParams.x, _BlueChannelParams.yz);
53 | color.a = MapSourceToChannel(_AlphaMap.SampleLevel(sampler_point_clamp, uv, 0), _AlphaChannelParams.x, _AlphaChannelParams.yz);
54 |
55 | _Output[id] = color;
56 | }
--------------------------------------------------------------------------------
/Resources/PackChannel.compute.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 96e7bd677a887f14aba97fecb97860c7
3 | ComputeShaderImporter:
4 | externalObjects: {}
5 | currentAPIMask: 4
6 | preprocessorOverride: 0
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Runtime.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 683872b7a9e58404d86a72f64355a908
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Runtime/Philira.SmartTexture.Runtime.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Philira.SmartTexture.Runtime",
3 | "references": [],
4 | "includePlatforms": [
5 | "Android",
6 | "Editor",
7 | "iOS",
8 | "LinuxStandalone64",
9 | "Lumin",
10 | "macOSStandalone",
11 | "PS4",
12 | "Switch",
13 | "tvOS",
14 | "WSA",
15 | "WebGL",
16 | "WindowsStandalone32",
17 | "WindowsStandalone64",
18 | "XboxOne"
19 | ],
20 | "excludePlatforms": [],
21 | "allowUnsafeCode": false,
22 | "overrideReferences": false,
23 | "precompiledReferences": [],
24 | "autoReferenced": true,
25 | "defineConstraints": [],
26 | "versionDefines": [],
27 | "noEngineReferences": false
28 | }
--------------------------------------------------------------------------------
/Runtime/Philira.SmartTexture.Runtime.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9e705d6a72d9a354b810376671ddb3ac
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Runtime/TextureChannelPacker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using UnityEngine.Experimental.Rendering;
4 |
5 | namespace SmartTexture
6 | {
7 | // TODO: Convert from sRGB to linear color space if necessary.
8 | // TODO: Texture compression / Format
9 |
10 | [Serializable]
11 | public enum TextureChannel
12 | {
13 | Red = 0,
14 | Green = 1,
15 | Blue = 2,
16 | Alpha = 3
17 | }
18 |
19 | [Serializable, Flags]
20 | public enum TextureChannelMask
21 | {
22 | Red = 1 << 0,
23 | Green = 1 << 1,
24 | Blue = 1 << 2,
25 | Alpha = 1 << 3,
26 | }
27 |
28 | ///
29 | /// Containts settings that apply color modifiers to each channel.
30 | ///
31 | [Serializable]
32 | public struct TexturePackingSettings
33 | {
34 | ///
35 | /// Outputs the inverted color (1.0 - color)
36 | ///
37 | public bool invertColor;
38 |
39 | ///
40 | /// Uses the combined rgb luminance factor.
41 | ///
42 | public bool useLuminance;
43 |
44 | ///
45 | /// Remaps the channel.
46 | ///
47 | public Vector2 remapRange;
48 |
49 | ///
50 | /// Outputs the selected channel.
51 | ///
52 | public TextureChannel channel;
53 | }
54 |
55 | public static class TextureExtension
56 | {
57 | static ComputeShader s_PackChannelCs;
58 |
59 | static ComputeShader packChannelCs
60 | {
61 | get
62 | {
63 | if (s_PackChannelCs == null)
64 | {
65 | s_PackChannelCs = Resources.Load("PackChannel");
66 | }
67 |
68 | return s_PackChannelCs;
69 | }
70 | }
71 |
72 | static readonly int s_RedMap = Shader.PropertyToID("_RedMap");
73 | static readonly int s_GreenMap = Shader.PropertyToID("_GreenMap");
74 | static readonly int s_BlueMap = Shader.PropertyToID("_BlueMap");
75 | static readonly int s_AlphaMap = Shader.PropertyToID("_AlphaMap");
76 |
77 | static readonly int s_RedChannelParams = Shader.PropertyToID("_RedChannelParams");
78 | static readonly int s_GreenChannelParams = Shader.PropertyToID("_GreenChannelParams");
79 | static readonly int s_BlueChannelParams = Shader.PropertyToID("_BlueChannelParams");
80 | static readonly int s_AlphaChannelParams = Shader.PropertyToID("_AlphaChannelParams");
81 |
82 | static readonly int s_Output = Shader.PropertyToID("_Output");
83 | static readonly int s_OutputSize = Shader.PropertyToID("_OutputSize");
84 |
85 | public static void PackChannels(this Texture2D mask, Texture2D[] inputTextures,
86 | TexturePackingSettings[] settings, GraphicsFormat graphicsFormat, bool srgb, bool mipmaps)
87 | {
88 | if (inputTextures == null || inputTextures.Length != 4)
89 | {
90 | Debug.LogError("Invalid parameter to PackChannels. An array of 4 textures is expected");
91 | return;
92 | }
93 |
94 | if (!packChannelCs)
95 | {
96 | Debug.LogError("Coudn't find `PackChannels` compute shader.");
97 | return;
98 | }
99 |
100 | if (settings == null)
101 | {
102 | settings = new TexturePackingSettings[4];
103 | for (int i = 0; i < settings.Length; ++i)
104 | {
105 | settings[i].remapRange = new Vector2(0.0f, 1.0f);
106 | }
107 | }
108 |
109 | int width = mask.width;
110 | int height = mask.height;
111 |
112 | packChannelCs.SetTexture(0, s_RedMap, inputTextures[0] != null ? inputTextures[0] : Texture2D.blackTexture);
113 | packChannelCs.SetTexture(0, s_GreenMap,
114 | inputTextures[1] != null ? inputTextures[1] : Texture2D.blackTexture);
115 | packChannelCs.SetTexture(0, s_BlueMap,
116 | inputTextures[2] != null ? inputTextures[2] : Texture2D.blackTexture);
117 | packChannelCs.SetTexture(0, s_AlphaMap,
118 | inputTextures[3] != null ? inputTextures[3] : Texture2D.blackTexture);
119 |
120 | packChannelCs.SetVector(s_RedChannelParams, GetShaderChannelParams(settings[0]));
121 | packChannelCs.SetVector(s_GreenChannelParams, GetShaderChannelParams(settings[1]));
122 | packChannelCs.SetVector(s_BlueChannelParams, GetShaderChannelParams(settings[2]));
123 | packChannelCs.SetVector(s_AlphaChannelParams, GetShaderChannelParams(settings[3]));
124 |
125 | var rtForm = GraphicsFormatUtility.GetRenderTextureFormat(graphicsFormat);
126 | var rtDesc = new RenderTextureDescriptor(width, height, rtForm, 0)
127 | {
128 | sRGB = srgb,
129 | useMipMap = mipmaps,
130 | #if UNITY_2020_1_OR_NEWER
131 | mipCount = mipmaps ? mask.mipmapCount : 1,
132 | #endif
133 | autoGenerateMips = false,
134 | enableRandomWrite = true,
135 | };
136 |
137 | var rt = new RenderTexture(rtDesc);
138 | rt.Create();
139 |
140 | packChannelCs.SetTexture(0, s_Output, rt);
141 | packChannelCs.SetVector(s_OutputSize, new Vector4(width, height, 1.0f / width, 1.0f / height));
142 | packChannelCs.Dispatch(0, (rt.width + 7) / 8, (rt.height + 7) / 8, 1);
143 |
144 | RenderTexture previous = RenderTexture.active;
145 | RenderTexture.active = rt;
146 |
147 | mask.ReadPixels(new Rect(0, 0, width, height), 0, 0, mipmaps);
148 | mask.Apply(mipmaps);
149 |
150 | RenderTexture.active = previous;
151 | rt.Release();
152 | }
153 |
154 | static Vector4 GetShaderChannelParams(in TexturePackingSettings settings)
155 | {
156 | float channel = settings.useLuminance ? 5 : (int) settings.channel + 1;
157 | channel *= (settings.invertColor ? -1.0f : 1.0f);
158 | return new Vector4(channel, settings.remapRange.x, settings.remapRange.y, 0.0f);
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/Runtime/TextureChannelPacker.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d8c40e436475247d587a32d3a1d49cec
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Shaders.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: edae5c0bd738c41dc86b46b3b5f0924e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Shaders/PackShader.shader:
--------------------------------------------------------------------------------
1 | Shader "Hidden/PackChannel"
2 | {
3 | Properties
4 | {
5 | _RedChannel("RedChannel", 2D) = "white" {}
6 | _GreenChannel("GreenChannel", 2D) = "white" {}
7 | _BlueChannel("BlueChannel", 2D) = "white" {}
8 | _AlphaChannel("AlphaChannel", 2D) = "white" {}
9 | _InvertColor("_InvertColor", Vector) = (0.0, 0.0, 0.0, 0.0)
10 | }
11 |
12 | HLSLINCLUDE
13 | Texture2D _RedChannel;
14 | Texture2D _GreenChannel;
15 | Texture2D _BlueChannel;
16 | Texture2D _AlphaChannel;
17 | sampler sampler_point_clamp;
18 |
19 | ENDHLSL
20 |
21 | SubShader
22 | {
23 | Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalRenderPipeline"}
24 |
25 | Pass
26 | {
27 | Tags { "LightMode"="Forward" }
28 |
29 | HLSLPROGRAM
30 | #pragma vertex vert
31 | #pragma fragment frag
32 |
33 | #include "HLSLSupport.cginc"
34 | #include "UnityShaderVariables.cginc"
35 |
36 | CBUFFER_START(UnityPerMaterial)
37 | float4 _RedChannel_TexelSize;
38 | half4 _InvertColor;
39 | CBUFFER_END
40 |
41 | float4 vert(float4 positionOS : POSITION) : SV_POSITION
42 | {
43 | return mul(UNITY_MATRIX_VP, mul(UNITY_MATRIX_M, float4(positionOS.xyz, 1.0)));
44 | //return TransformObjectToHClip(positionOS.xyz);
45 | }
46 |
47 | half4 frag(float4 positionHCS : SV_POSITION) : SV_Target
48 | {
49 | float2 uv = positionHCS * _RedChannel_TexelSize.xy;
50 | half r = _RedChannel.Sample(sampler_point_clamp, uv).r;
51 | half g = _GreenChannel.Sample(sampler_point_clamp, uv).r;
52 | half b = _BlueChannel.Sample(sampler_point_clamp, uv).r;
53 | half a = _AlphaChannel.Sample(sampler_point_clamp, uv).r;
54 |
55 | if (_InvertColor.x > 0.0)
56 | r = 1.0 - r;
57 |
58 | if (_InvertColor.g > 0.0)
59 | g = 1.0 - g;
60 |
61 | if (_InvertColor.b > 0.0)
62 | b = 1.0 - b;
63 |
64 | if (_InvertColor.a > 0.0)
65 | a = 1.0 - a;
66 | return half4(r, g, b, a);
67 | }
68 | ENDHLSL
69 | }
70 | }
71 |
72 | SubShader
73 | {
74 | Pass
75 | {
76 | HLSLPROGRAM
77 | #pragma vertex vert
78 | #pragma fragment frag
79 |
80 | #include "UnityCG.cginc"
81 |
82 | CBUFFER_START(UnityPerMaterial)
83 | float4 _RedChannel_TexelSize;
84 | half4 _InvertColor;
85 | CBUFFER_END
86 |
87 | float4 vert(float4 positionOS : POSITION) : SV_POSITION
88 | {
89 | return UnityObjectToClipPos(positionOS.xyz);
90 | }
91 |
92 | half4 frag(float4 positionHCS : SV_POSITION) : SV_Target
93 | {
94 | float2 uv = positionHCS * _RedChannel_TexelSize.xy;
95 | half r = _RedChannel.Sample(sampler_point_clamp, uv).r;
96 | half g = _GreenChannel.Sample(sampler_point_clamp, uv).r;
97 | half b = _BlueChannel.Sample(sampler_point_clamp, uv).r;
98 | half a = _AlphaChannel.Sample(sampler_point_clamp, uv).r;
99 |
100 | if (_InvertColor.x > 0.0)
101 | r = 1.0 - r;
102 |
103 | if (_InvertColor.g > 0.0)
104 | g = 1.0 - g;
105 |
106 | if (_InvertColor.b > 0.0)
107 | b = 1.0 - b;
108 |
109 | if (_InvertColor.a > 0.0)
110 | a = 1.0 - a;
111 | return half4(r, g, b, a);
112 | }
113 | ENDHLSL
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Shaders/PackShader.shader.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7301b3a1d9d6947099451599aba74fde
3 | ShaderImporter:
4 | externalObjects: {}
5 | defaultTextures: []
6 | nonModifiableTextures: []
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b06745750b9594648ae6e8a52b3dcf9e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8b831c344cdf9f14ab95279309d511a5
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Philira.SmartTexture.Editor.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Philira.SmartTexture.Editor.Tests",
3 | "references": [
4 | "GUID:27619889b8ba8c24980f49ee34dbb44a",
5 | "GUID:0acc523941302664db1f4e527237feb3",
6 | "GUID:9e705d6a72d9a354b810376671ddb3ac"
7 | ],
8 | "includePlatforms": [
9 | "Editor"
10 | ],
11 | "excludePlatforms": [],
12 | "allowUnsafeCode": false,
13 | "overrideReferences": true,
14 | "precompiledReferences": [
15 | "nunit.framework.dll"
16 | ],
17 | "autoReferenced": false,
18 | "defineConstraints": [
19 | "UNITY_INCLUDE_TESTS"
20 | ],
21 | "versionDefines": [],
22 | "noEngineReferences": false
23 | }
--------------------------------------------------------------------------------
/Tests/Editor/Philira.SmartTexture.Editor.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4d7bdb677fe99a24bb5c724d97ffd1c3
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.phi-lira.smarttexture",
3 | "description": "Allows to create smart texture assets for Unity.",
4 | "version": "0.1.0",
5 | "unity": "2019.3",
6 | "displayName": "Smart Texture",
7 | "dependencies": {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 86eeb02d66d12f945ac8f9ca24c90772
3 | PackageManifestImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------