├── .gitignore
├── CHANGELOG.md
├── CHANGELOG.md.meta
├── Editor.meta
├── Editor
├── SmartTextureImporter.cs
├── SmartTextureImporter.cs.meta
├── SmartTextureImporterEditor.cs
└── SmartTextureImporterEditor.cs.meta
├── LICENSE
├── LICENSE.meta
├── Philira.SmartTexture.Editor.asmdef
├── Philira.SmartTexture.Editor.asmdef.meta
├── README.md
├── README.md.meta
├── Shaders.meta
├── Shaders
├── PackShader.mat
├── PackShader.mat.meta
├── PackShader.shader
└── PackShader.shader.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 | All notable changes to this package are documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 | ## [0.1.0] - 2020-05-16
8 | ### Added
9 | - 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/SmartTextureImporter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using UnityEditor;
5 |
6 | using UnityEngine;
7 | using UnityEngine.Rendering;
8 | using Object = UnityEngine.Object;
9 |
10 | [UnityEditor.AssetImporters.ScriptedImporter(k_SmartTextureVersion, k_SmartTextureExtesion)]
11 | public class SmartTextureImporter : UnityEditor.AssetImporters.ScriptedImporter
12 | {
13 | public const string k_SmartTextureExtesion = "smartex";
14 | public const int k_SmartTextureVersion = 1;
15 | public const int k_MenuPriority = 320;
16 |
17 | [Serializable] internal class InputProperty { public string propertyName; }
18 | [Serializable] class InputTexture : InputProperty { public Texture value; }
19 | [Serializable] class InputFloat : InputProperty { public float value; }
20 | [Serializable] class InputColor : InputProperty { [ColorUsage(true, true)] public Color value; }
21 | [Serializable] class InputVector : InputProperty { public Vector4 value; }
22 |
23 | [Serializable] class Inputs {
24 | public InputTexture[] m_Textures;
25 | public InputFloat[] m_Floats;
26 | public InputColor[] m_Colors;
27 | public InputVector[] m_Vectors;
28 |
29 | }
30 | // Input Texture Settings
31 | [SerializeField] Material m_BlitMaterial;
32 | [SerializeField] Vector2Int m_OutputSize;
33 | [SerializeField] bool m_Preview;
34 | [SerializeField] Inputs m_Inputs;
35 |
36 | // Output Texture Settings
37 | [SerializeField] bool m_HasAlpha = false;
38 | [SerializeField] bool m_IsReadable = false;
39 | [SerializeField] bool m_sRGBTexture = false;
40 |
41 | [SerializeField] bool m_EnableMipMap = true;
42 | [SerializeField] bool m_StreamingMipMaps = false;
43 | [SerializeField] int m_StreamingMipMapPriority = 0;
44 |
45 | // TODO: MipMap Generation, is it possible to configure?
46 | //[SerializeField] bool m_BorderMipMaps = false;
47 | //[SerializeField] TextureImporterMipFilter m_MipMapFilter = TextureImporterMipFilter.BoxFilter;
48 | //[SerializeField] bool m_MipMapsPreserveCoverage = false;
49 | //[SerializeField] bool m_FadeoutMipMaps = false;
50 |
51 | [SerializeField] FilterMode m_FilterMode = FilterMode.Bilinear;
52 | [SerializeField] TextureWrapMode m_WrapMode = TextureWrapMode.Repeat;
53 | [SerializeField] int m_AnisotricLevel = 1;
54 |
55 | [SerializeField] TextureImporterPlatformSettings m_TexturePlatformSettings = new TextureImporterPlatformSettings();
56 |
57 | [SerializeField] TextureFormat m_TextureFormat = TextureFormat.ARGB32;
58 | [SerializeField] bool m_UseExplicitTextureFormat = false;
59 |
60 | [MenuItem("Assets/Create/Smart Texture", priority = k_MenuPriority)]
61 | static void CreateSmartTextureMenuItem()
62 | {
63 | // Asset creation code from pschraut Texture2DArrayImporter
64 | // https://github.com/pschraut/UnityTexture2DArrayImportPipeline/blob/master/Editor/Texture2DArrayImporter.cs#L360-L383
65 | string directoryPath = "Assets";
66 | foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
67 | {
68 | directoryPath = AssetDatabase.GetAssetPath(obj);
69 | if (!string.IsNullOrEmpty(directoryPath) && File.Exists(directoryPath))
70 | {
71 | directoryPath = Path.GetDirectoryName(directoryPath);
72 | break;
73 | }
74 | }
75 |
76 | directoryPath = directoryPath.Replace("\\", "/");
77 | if (directoryPath.Length > 0 && directoryPath[directoryPath.Length - 1] != '/')
78 | directoryPath += "/";
79 | if (string.IsNullOrEmpty(directoryPath))
80 | directoryPath = "Assets/";
81 |
82 | var fileName = string.Format("SmartTexture.{0}", k_SmartTextureExtesion);
83 | directoryPath = AssetDatabase.GenerateUniqueAssetPath(directoryPath + fileName);
84 | ProjectWindowUtil.CreateAssetWithContent(directoryPath,
85 | "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.");
86 | }
87 |
88 | public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
89 | {
90 | int width = m_TexturePlatformSettings.maxTextureSize;
91 | int height = m_TexturePlatformSettings.maxTextureSize;
92 | var maxSize = m_OutputSize;
93 |
94 | foreach (var t in m_Inputs.m_Textures)
95 | {
96 | if (t.value == null) continue;
97 | if (m_OutputSize.x == 0 && t.value.width > maxSize.x) maxSize.x = t.value.width;
98 | if (m_OutputSize.y == 0 && t.value.height > maxSize.y) maxSize.y = t.value.height;
99 | }
100 | var canGenerateTexture = maxSize != default;
101 | maxSize.x = Mathf.Max(maxSize.x, 1);
102 | maxSize.y = Mathf.Max(maxSize.y, 1);
103 |
104 | //Mimic default importer. We use max size unless assets are smaller
105 | width = width < maxSize.x ? width : maxSize.x;
106 | height = height < maxSize.y ? height : maxSize.y;
107 |
108 | Texture2D texture = new Texture2D(width, height, m_HasAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, m_EnableMipMap, m_sRGBTexture)
109 | {
110 | filterMode = m_FilterMode,
111 | wrapMode = m_WrapMode,
112 | anisoLevel = m_AnisotricLevel,
113 | };
114 |
115 | if (canGenerateTexture)
116 | {
117 | //Only attempt to apply any settings if the inputs exist
118 |
119 | PackChannels(m_BlitMaterial, texture, m_Inputs);
120 |
121 | // Mark all input textures as dependency to the texture array.
122 | // This causes the texture array to get re-generated when any input texture changes or when the build target changed.
123 | foreach (var t in m_Inputs.m_Textures)
124 | {
125 | if (t.value != null)
126 | {
127 | var path = AssetDatabase.GetAssetPath(t.value);
128 | ctx.DependsOnSourceAsset(path);
129 | }
130 | }
131 |
132 | // TODO: Seems like we need to call TextureImporter.SetPlatformTextureSettings to register/apply platform
133 | // settings. However we can't subclass from TextureImporter... Is there other way?
134 |
135 | //Currently just supporting one compression format in liew of TextureImporter.SetPlatformTextureSettings
136 | if (m_UseExplicitTextureFormat)
137 | EditorUtility.CompressTexture(texture, m_TextureFormat, 100);
138 | else if (m_TexturePlatformSettings.textureCompression != TextureImporterCompression.Uncompressed)
139 | texture.Compress(m_TexturePlatformSettings.textureCompression == TextureImporterCompression.CompressedHQ);
140 |
141 | ApplyPropertiesViaSerializedObj(texture);
142 | }
143 |
144 | //If we pass the tex to the 3rd arg we can have it show in an Icon as normal, maybe configurable?
145 | //ctx.AddObjectToAsset("mask", texture, texture);
146 | ctx.AddObjectToAsset("mask", texture, texture);
147 | ctx.SetMainObject(texture);
148 | }
149 |
150 | static void PackChannels(Material mat, Texture2D mask, Inputs inputs)
151 | {
152 | int width = mask.width;
153 | int height = mask.height;
154 |
155 | mat = new Material(mat);
156 |
157 | foreach (var i in inputs.m_Textures) mat.SetTexture(i.propertyName, i.value);
158 | foreach (var i in inputs.m_Floats) mat.SetFloat(i.propertyName, i.value);
159 | foreach (var i in inputs.m_Colors) mat.SetColor(i.propertyName, i.value);
160 | foreach (var i in inputs.m_Vectors) mat.SetVector(i.propertyName, i.value);
161 |
162 | var rt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
163 | RenderTexture previous = RenderTexture.active;
164 | RenderTexture.active = rt;
165 |
166 | CommandBuffer cmd = new CommandBuffer();
167 | cmd.Blit(null, rt, mat);
168 | cmd.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
169 | Graphics.ExecuteCommandBuffer(cmd);
170 | mask.ReadPixels(new Rect(0, 0, width, height), 0, 0);
171 | mask.Apply();
172 |
173 | RenderTexture.active = previous;
174 | RenderTexture.ReleaseTemporary(rt);
175 | }
176 |
177 | void ApplyPropertiesViaSerializedObj(Texture tex)
178 | {
179 | var so = new SerializedObject(tex);
180 |
181 | so.FindProperty("m_IsReadable").boolValue = m_IsReadable;
182 | so.FindProperty("m_StreamingMipmaps").boolValue = m_StreamingMipMaps;
183 | so.FindProperty("m_StreamingMipmapsPriority").intValue = m_StreamingMipMapPriority;
184 | //Set ColorSpace on ctr instead
185 | //so.FindProperty("m_ColorSpace").intValue = (int)(m_sRGBTexture ? ColorSpace.Gamma : ColorSpace.Linear);
186 |
187 | so.ApplyModifiedPropertiesWithoutUndo();
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/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 | #if UNITY_EDITOR
2 | using System;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 |
7 | [CustomEditor(typeof(SmartTextureImporter), true)]
8 | class SmartTextureImporterEditor : UnityEditor.AssetImporters.ScriptedImporterEditor
9 | {
10 | [CustomPropertyDrawer(typeof(SmartTextureImporter.InputProperty), true)]
11 | class InputPropertyDrawer : PropertyDrawer
12 | {
13 | GUIContent temp = new GUIContent();
14 |
15 | public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
16 | {
17 | var name = property.FindPropertyRelative("propertyName");
18 | var value = property.FindPropertyRelative("value");
19 |
20 | rect.width /= 2;
21 | EditorGUI.PropertyField(rect, name, GUIContent.none);
22 |
23 | EditorGUIUtility.labelWidth = 15;
24 | rect.x += rect.width;
25 | if (value.propertyType == SerializedPropertyType.Vector4){
26 | rect.width /= 4;
27 | temp.text = " x"; EditorGUI.PropertyField(rect, value.FindPropertyRelative("x"), temp); rect.x += rect.width;
28 | temp.text = " y"; EditorGUI.PropertyField(rect, value.FindPropertyRelative("y"), temp); rect.x += rect.width;
29 | temp.text = " z"; EditorGUI.PropertyField(rect, value.FindPropertyRelative("z"), temp); rect.x += rect.width;
30 | temp.text = " w"; EditorGUI.PropertyField(rect, value.FindPropertyRelative("w"), temp);
31 | }
32 | else{
33 | temp.text = " ";
34 | EditorGUI.PropertyField(rect, value, temp);
35 | }
36 | }
37 | }
38 |
39 | internal static class Styles
40 | {
41 | public static readonly GUIContent readWrite = EditorGUIUtility.TrTextContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code.");
42 | public static readonly GUIContent generateMipMaps = EditorGUIUtility.TrTextContent("Generate Mip Maps");
43 | public static readonly GUIContent streamingMipMaps = EditorGUIUtility.TrTextContent("Streaming Mip Maps");
44 | public static readonly GUIContent streamingMipMapsPrio = EditorGUIUtility.TrTextContent("Streaming Mip Maps Priority");
45 | public static readonly GUIContent sRGBTexture = EditorGUIUtility.TrTextContent("sRGB (Color Texture)", "Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).");
46 |
47 | public static readonly GUIContent textureFilterMode = EditorGUIUtility.TrTextContent("Filter Mode");
48 | public static readonly GUIContent textureWrapMode = EditorGUIUtility.TrTextContent("Wrap Mode");
49 | public static readonly GUIContent textureAnisotropicLevel = EditorGUIUtility.TrTextContent("Anisotropic Level");
50 |
51 | public static readonly GUIContent crunchCompression = EditorGUIUtility.TrTextContent("Crunch");
52 | public static readonly GUIContent useExplicitTextureFormat = EditorGUIUtility.TrTextContent("Use Explicit Texture Format");
53 |
54 | public static readonly string[] textureSizeOptions =
55 | {
56 | "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192",
57 | };
58 |
59 | public static readonly string[] textureCompressionOptions = Enum.GetNames(typeof(TextureImporterCompression));
60 | public static readonly string[] textureFormat = Enum.GetNames(typeof(TextureFormat));
61 | public static readonly string[] resizeAlgorithmOptions = Enum.GetNames(typeof(TextureResizeAlgorithm));
62 | }
63 |
64 | SerializedProperty m_Inputs;
65 | SerializedProperty m_BlitMaterial;
66 | SerializedProperty m_OutputSize;
67 | SerializedProperty m_Preview;
68 |
69 | SerializedProperty m_IsReadableProperty;
70 | SerializedProperty m_sRGBTextureProperty;
71 | SerializedProperty m_HasAlpha;
72 |
73 | SerializedProperty m_EnableMipMap;
74 | SerializedProperty m_StreamingMipMaps;
75 | SerializedProperty m_StreamingMipMapPriority;
76 |
77 | SerializedProperty m_FilterModeProperty;
78 | SerializedProperty m_WrapModeProperty;
79 | SerializedProperty m_AnisotropiceLevelPropery;
80 |
81 | SerializedProperty m_TexturePlatformSettings;
82 |
83 | SerializedProperty m_TextureFormat;
84 | SerializedProperty m_UseExplicitTextureFormat;
85 |
86 | bool m_ShowAdvanced = false;
87 |
88 | const string k_AdvancedTextureSettingName = "SmartTextureImporterShowAdvanced";
89 |
90 | public override void OnEnable()
91 | {
92 | base.OnEnable();
93 | CacheSerializedProperties();
94 | }
95 |
96 | public override void OnInspectorGUI()
97 | {
98 | serializedObject.Update();
99 |
100 | m_ShowAdvanced = EditorPrefs.GetBool(k_AdvancedTextureSettingName, m_ShowAdvanced);
101 |
102 | EditorGUI.BeginChangeCheck();
103 |
104 | EditorGUILayout.BeginHorizontal();
105 | ApplyRevertGUI();
106 | if (GUILayout.Button("Repack"))
107 | ApplyAndImport();
108 | GUILayout.FlexibleSpace();
109 | EditorGUILayout.EndHorizontal();
110 | GUILayout.Space(5);
111 |
112 | EditorGUILayout.PropertyField(m_BlitMaterial);
113 | EditorGUILayout.PropertyField(m_OutputSize);
114 |
115 | EditorGUILayout.PropertyField(m_Inputs);
116 |
117 | if (m_EnableMipMap.isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(m_EnableMipMap.isExpanded, "Output Texture"))
118 | {
119 | // TODO: Figure out how to apply TextureImporterSettings on ScriptedImporter
120 | EditorGUILayout.PropertyField(m_HasAlpha);
121 | EditorGUILayout.PropertyField(m_IsReadableProperty, Styles.readWrite);
122 | EditorGUILayout.PropertyField(m_sRGBTextureProperty, Styles.sRGBTexture);
123 | EditorGUILayout.Space();
124 |
125 | EditorGUILayout.PropertyField(m_EnableMipMap, Styles.generateMipMaps);
126 | EditorGUILayout.PropertyField(m_StreamingMipMaps, Styles.streamingMipMaps);
127 | EditorGUILayout.PropertyField(m_StreamingMipMapPriority, Styles.streamingMipMapsPrio);
128 | EditorGUILayout.Space();
129 |
130 | EditorGUILayout.PropertyField(m_FilterModeProperty, Styles.textureFilterMode);
131 | EditorGUILayout.PropertyField(m_WrapModeProperty, Styles.textureWrapMode);
132 |
133 | EditorGUILayout.IntSlider(m_AnisotropiceLevelPropery, 0, 16, Styles.textureAnisotropicLevel);
134 | EditorGUILayout.Space();
135 | }
136 | EditorGUILayout.EndFoldoutHeaderGroup();
137 |
138 | // TODO: Figure out how to apply PlatformTextureImporterSettings on ScriptedImporter
139 | DrawTextureImporterSettings();
140 | serializedObject.ApplyModifiedProperties();
141 | }
142 |
143 | void DrawTextureImporterSettings()
144 | {
145 | SerializedProperty maxTextureSize = m_TexturePlatformSettings.FindPropertyRelative("m_MaxTextureSize");
146 | SerializedProperty resizeAlgorithm =
147 | m_TexturePlatformSettings.FindPropertyRelative("m_ResizeAlgorithm");
148 | SerializedProperty textureCompression =
149 | m_TexturePlatformSettings.FindPropertyRelative("m_TextureCompression");
150 | SerializedProperty textureCompressionCrunched =
151 | m_TexturePlatformSettings.FindPropertyRelative("m_CrunchedCompression");
152 |
153 | if (m_TexturePlatformSettings.isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(m_TexturePlatformSettings.isExpanded, "Texture Platform Settings"))
154 | {
155 | EditorGUI.BeginChangeCheck();
156 | int sizeOption = EditorGUILayout.Popup("Texture Size", (int)Mathf.Log(maxTextureSize.intValue, 2) - 5, Styles.textureSizeOptions);
157 | if (EditorGUI.EndChangeCheck())
158 | maxTextureSize.intValue = 32 << sizeOption;
159 |
160 | EditorGUI.BeginChangeCheck();
161 | int resizeOption = EditorGUILayout.Popup("Resize Algorithm", resizeAlgorithm.intValue, Styles.resizeAlgorithmOptions);
162 | if (EditorGUI.EndChangeCheck())
163 | resizeAlgorithm.intValue = resizeOption;
164 |
165 | //EditorGUILayout.LabelField("Compression", EditorStyles.boldLabel);
166 | //using (new EditorGUI.IndentLevelScope())
167 | {
168 | EditorGUI.BeginChangeCheck();
169 | bool explicitFormat = EditorGUILayout.Toggle(Styles.useExplicitTextureFormat, m_UseExplicitTextureFormat.boolValue);
170 | if (EditorGUI.EndChangeCheck())
171 | m_UseExplicitTextureFormat.boolValue = explicitFormat;
172 |
173 | using (new EditorGUI.DisabledScope(explicitFormat))
174 | {
175 | GUILayout.BeginHorizontal();
176 | EditorGUI.BeginChangeCheck();
177 | int compressionOption = EditorGUILayout.Popup("Texture Type", textureCompression.intValue, Styles.textureCompressionOptions);
178 | if (EditorGUI.EndChangeCheck())
179 | textureCompression.intValue = compressionOption;
180 |
181 | EditorGUI.BeginChangeCheck();
182 | var oldWidth = EditorGUIUtility.labelWidth;
183 | EditorGUIUtility.labelWidth = 100f;
184 | bool crunchOption = EditorGUILayout.Toggle(Styles.crunchCompression, textureCompressionCrunched.boolValue);
185 | EditorGUIUtility.labelWidth = oldWidth;
186 | if (EditorGUI.EndChangeCheck())
187 | textureCompressionCrunched.boolValue = crunchOption;
188 | GUILayout.EndHorizontal();
189 | }
190 |
191 | using (new EditorGUI.DisabledScope(!explicitFormat))
192 | {
193 | EditorGUI.BeginChangeCheck();
194 | int format = EditorGUILayout.EnumPopup("Texture Format", (TextureFormat)m_TextureFormat.intValue).GetHashCode();//("Compression", m_TextureFormat.enumValueIndex, Styles.textureFormat);
195 | if (EditorGUI.EndChangeCheck())
196 | m_TextureFormat.intValue = format;
197 | }
198 | }
199 | }
200 | EditorGUILayout.EndFoldoutHeaderGroup();
201 | }
202 |
203 | void CacheSerializedProperties()
204 | {
205 | m_BlitMaterial = serializedObject.FindProperty("m_BlitMaterial");
206 | m_OutputSize = serializedObject.FindProperty("m_OutputSize");
207 | m_Inputs = serializedObject.FindProperty("m_Inputs");
208 | m_Preview = serializedObject.FindProperty("m_Preview");
209 |
210 | m_IsReadableProperty = serializedObject.FindProperty("m_IsReadable");
211 | m_sRGBTextureProperty = serializedObject.FindProperty("m_sRGBTexture");
212 | m_HasAlpha = serializedObject.FindProperty("m_HasAlpha");
213 |
214 | m_EnableMipMap = serializedObject.FindProperty("m_EnableMipMap");
215 | m_StreamingMipMaps = serializedObject.FindProperty("m_StreamingMipMaps");
216 | m_StreamingMipMapPriority = serializedObject.FindProperty("m_StreamingMipMapPriority");
217 |
218 | m_FilterModeProperty = serializedObject.FindProperty("m_FilterMode");
219 | m_WrapModeProperty = serializedObject.FindProperty("m_WrapMode");
220 | m_AnisotropiceLevelPropery = serializedObject.FindProperty("m_AnisotricLevel");
221 |
222 | m_TexturePlatformSettings = serializedObject.FindProperty("m_TexturePlatformSettings");
223 | m_TextureFormat = serializedObject.FindProperty("m_TextureFormat");
224 | m_UseExplicitTextureFormat = serializedObject.FindProperty("m_UseExplicitTextureFormat");
225 | }
226 | }
227 | #endif
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/Philira.SmartTexture.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Phillira.SmartTexture.Editor",
3 | "references": [
4 | "GUID:9e705d6a72d9a354b810376671ddb3ac"
5 | ],
6 | "includePlatforms": [
7 | "Editor"
8 | ],
9 | "excludePlatforms": [],
10 | "allowUnsafeCode": false,
11 | "overrideReferences": true,
12 | "precompiledReferences": [],
13 | "autoReferenced": false,
14 | "defineConstraints": [],
15 | "versionDefines": [],
16 | "noEngineReferences": false
17 | }
--------------------------------------------------------------------------------
/Philira.SmartTexture.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73270a5d45254f640ba02b1830980ad4
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SmartTexture Asset for Unity
2 |
3 | ## Modified by Neonage
4 | * Pack with any custom material/shader
5 | * Provide material properties per-texture
6 |
7 | https://user-images.githubusercontent.com/29812914/172454566-8936e34e-7108-48f5-ba88-94f84b247a3d.mp4
8 |
9 |
10 |
11 | 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.
12 | SmartTextures work as a regular 2D texture asset and you can assign it to material inspectors.
13 |
14 | 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.
15 |
16 |
17 |
18 | ---
19 | **NOTE**
20 |
21 | This package is still a Proof of Concept (POC) and it's still experimental.
22 | You can request features or submit bugs by creating new issues in the issue tab. For feature request please add "enhancement" label.
23 |
24 | ---
25 |
26 |
27 | ## Installation
28 | SmartTexture is a unity package and you can install it from Package Manager.
29 |
30 | Option 1: [Install package via Github](https://docs.unity3d.com/Manual/upm-ui-giturl.html).
31 |
32 | Option 2: Clone or download this Github project and [install it as a local package](https://docs.unity3d.com/Manual/upm-ui-local.html).
33 |
34 | ## How to use
35 | 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`.
36 |
37 |
38 | 2) An asset will be created in your project.
39 |
40 |
41 | 3) On the asset inspector you can configure input textures and texture settings for your smart texture.
42 | 4) Hit `Apply` button to generate the texture with selected settings.
43 |
44 |
45 | 5) Now you can use this texture as any regular 2D texture in your project.
46 |
47 |
48 | ## Acknowledgements
49 | * 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.
50 | * Thanks to [Aras P.](https://twitter.com/aras_p) for guidance and ideas on how to create this.
51 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 348769316597fe54b9db2cd435d11a02
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Shaders.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: edae5c0bd738c41dc86b46b3b5f0924e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Shaders/PackShader.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-7177970478230962508
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 11
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | version: 4
16 | --- !u!21 &2100000
17 | Material:
18 | serializedVersion: 6
19 | m_ObjectHideFlags: 0
20 | m_CorrespondingSourceObject: {fileID: 0}
21 | m_PrefabInstance: {fileID: 0}
22 | m_PrefabAsset: {fileID: 0}
23 | m_Name: PackShader
24 | m_Shader: {fileID: 4800000, guid: 7301b3a1d9d6947099451599aba74fde, type: 3}
25 | m_ShaderKeywords:
26 | m_LightmapFlags: 4
27 | m_EnableInstancingVariants: 0
28 | m_DoubleSidedGI: 0
29 | m_CustomRenderQueue: -1
30 | stringTagMap: {}
31 | disabledShaderPasses: []
32 | m_SavedProperties:
33 | serializedVersion: 3
34 | m_TexEnvs:
35 | - _AlphaChannel:
36 | m_Texture: {fileID: 0}
37 | m_Scale: {x: 1, y: 1}
38 | m_Offset: {x: 0, y: 0}
39 | - _BaseMap:
40 | m_Texture: {fileID: 0}
41 | m_Scale: {x: 1, y: 1}
42 | m_Offset: {x: 0, y: 0}
43 | - _BlueChannel:
44 | m_Texture: {fileID: 0}
45 | m_Scale: {x: 1, y: 1}
46 | m_Offset: {x: 0, y: 0}
47 | - _BumpMap:
48 | m_Texture: {fileID: 0}
49 | m_Scale: {x: 1, y: 1}
50 | m_Offset: {x: 0, y: 0}
51 | - _DetailAlbedoMap:
52 | m_Texture: {fileID: 0}
53 | m_Scale: {x: 1, y: 1}
54 | m_Offset: {x: 0, y: 0}
55 | - _DetailMask:
56 | m_Texture: {fileID: 0}
57 | m_Scale: {x: 1, y: 1}
58 | m_Offset: {x: 0, y: 0}
59 | - _DetailNormalMap:
60 | m_Texture: {fileID: 0}
61 | m_Scale: {x: 1, y: 1}
62 | m_Offset: {x: 0, y: 0}
63 | - _EmissionMap:
64 | m_Texture: {fileID: 0}
65 | m_Scale: {x: 1, y: 1}
66 | m_Offset: {x: 0, y: 0}
67 | - _GreenChannel:
68 | m_Texture: {fileID: 0}
69 | m_Scale: {x: 1, y: 1}
70 | m_Offset: {x: 0, y: 0}
71 | - _MainTex:
72 | m_Texture: {fileID: 0}
73 | m_Scale: {x: 1, y: 1}
74 | m_Offset: {x: 0, y: 0}
75 | - _MetallicGlossMap:
76 | m_Texture: {fileID: 0}
77 | m_Scale: {x: 1, y: 1}
78 | m_Offset: {x: 0, y: 0}
79 | - _OcclusionMap:
80 | m_Texture: {fileID: 0}
81 | m_Scale: {x: 1, y: 1}
82 | m_Offset: {x: 0, y: 0}
83 | - _ParallaxMap:
84 | m_Texture: {fileID: 0}
85 | m_Scale: {x: 1, y: 1}
86 | m_Offset: {x: 0, y: 0}
87 | - _RedChannel:
88 | m_Texture: {fileID: 0}
89 | m_Scale: {x: 1, y: 1}
90 | m_Offset: {x: 0, y: 0}
91 | - _SpecGlossMap:
92 | m_Texture: {fileID: 0}
93 | m_Scale: {x: 1, y: 1}
94 | m_Offset: {x: 0, y: 0}
95 | - unity_Lightmaps:
96 | m_Texture: {fileID: 0}
97 | m_Scale: {x: 1, y: 1}
98 | m_Offset: {x: 0, y: 0}
99 | - unity_LightmapsInd:
100 | m_Texture: {fileID: 0}
101 | m_Scale: {x: 1, y: 1}
102 | m_Offset: {x: 0, y: 0}
103 | - unity_ShadowMasks:
104 | m_Texture: {fileID: 0}
105 | m_Scale: {x: 1, y: 1}
106 | m_Offset: {x: 0, y: 0}
107 | m_Floats:
108 | - _AlphaClip: 0
109 | - _Blend: 0
110 | - _BumpScale: 1
111 | - _ClearCoatMask: 0
112 | - _ClearCoatSmoothness: 0
113 | - _Cull: 2
114 | - _Cutoff: 0.5
115 | - _DetailAlbedoMapScale: 1
116 | - _DetailNormalMapScale: 1
117 | - _DstBlend: 0
118 | - _EnvironmentReflections: 1
119 | - _GlossMapScale: 0
120 | - _Glossiness: 0
121 | - _GlossyReflections: 0
122 | - _Metallic: 0
123 | - _OcclusionStrength: 1
124 | - _Parallax: 0.005
125 | - _QueueOffset: 0
126 | - _ReceiveShadows: 1
127 | - _Smoothness: 0.5
128 | - _SmoothnessTextureChannel: 0
129 | - _SpecularHighlights: 1
130 | - _SrcBlend: 1
131 | - _Surface: 0
132 | - _WorkflowMode: 1
133 | - _ZWrite: 1
134 | m_Colors:
135 | - _BaseColor: {r: 1, g: 1, b: 1, a: 1}
136 | - _Color: {r: 1, g: 1, b: 1, a: 1}
137 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
138 | - _InvertColor: {r: 0, g: 0, b: 0, a: 0}
139 | - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
140 | m_BuildTextureStacks: []
141 |
--------------------------------------------------------------------------------
/Shaders/PackShader.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c1fe2aa9e1273b148a173ec79df93dc7
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 2100000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Shaders/PackShader.shader:
--------------------------------------------------------------------------------
1 | Shader "Blit/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"="UniversalForward" }
28 |
29 | HLSLPROGRAM
30 | #pragma vertex vert
31 | #pragma fragment frag
32 |
33 | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
34 |
35 | CBUFFER_START(UnityPerMaterial)
36 | float4 _RedChannel_TexelSize;
37 | half4 _InvertColor;
38 | CBUFFER_END
39 |
40 | float4 vert(float4 positionOS : POSITION) : SV_POSITION
41 | {
42 | return TransformObjectToHClip(positionOS.xyz);
43 | }
44 |
45 | half4 frag(float4 positionHCS : SV_POSITION) : SV_Target
46 | {
47 | float2 uv = positionHCS * _RedChannel_TexelSize.xy;
48 | half r = _RedChannel.Sample(sampler_point_clamp, uv).r;
49 | half g = _GreenChannel.Sample(sampler_point_clamp, uv).r;
50 | half b = _BlueChannel.Sample(sampler_point_clamp, uv).r;
51 | half a = _AlphaChannel.Sample(sampler_point_clamp, uv).r;
52 |
53 | if (_InvertColor.x > 0.0)
54 | r = 1.0 - r;
55 |
56 | if (_InvertColor.g > 0.0)
57 | g = 1.0 - g;
58 |
59 | if (_InvertColor.b > 0.0)
60 | b = 1.0 - b;
61 |
62 | if (_InvertColor.a > 0.0)
63 | a = 1.0 - a;
64 | return half4(r, g, b, a);
65 | }
66 | ENDHLSL
67 | }
68 | }
69 |
70 | SubShader
71 | {
72 | Pass
73 | {
74 | HLSLPROGRAM
75 | #pragma vertex vert
76 | #pragma fragment frag
77 |
78 | #include "UnityCG.cginc"
79 |
80 | CBUFFER_START(UnityPerMaterial)
81 | float4 _RedChannel_TexelSize;
82 | half4 _InvertColor;
83 | CBUFFER_END
84 |
85 | float4 vert(float4 positionOS : POSITION) : SV_POSITION
86 | {
87 | return UnityObjectToClipPos(positionOS.xyz);
88 | }
89 |
90 | half4 frag(float4 positionHCS : SV_POSITION) : SV_Target
91 | {
92 | float2 uv = positionHCS * _RedChannel_TexelSize.xy;
93 | half r = _RedChannel.Sample(sampler_point_clamp, uv).r;
94 | half g = _GreenChannel.Sample(sampler_point_clamp, uv).r;
95 | half b = _BlueChannel.Sample(sampler_point_clamp, uv).r;
96 | half a = _AlphaChannel.Sample(sampler_point_clamp, uv).r;
97 |
98 | if (_InvertColor.x > 0.0)
99 | r = 1.0 - r;
100 |
101 | if (_InvertColor.g > 0.0)
102 | g = 1.0 - g;
103 |
104 | if (_InvertColor.b > 0.0)
105 | b = 1.0 - b;
106 |
107 | if (_InvertColor.a > 0.0)
108 | a = 1.0 - a;
109 | return half4(r, g, b, a);
110 | }
111 | ENDHLSL
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------