Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by amirabiri · Oct 23, 2011 at 02:03 PM · shadereditor

A way to iterate/enumerate shader properties?

I'm trying to automatically scan materials in my project from an editor script to find usages of a given texture.

I was able to successfully iterate all materials using the assets database. However when it comes to the question of "is this material using this texture" I've come across a problem since the answer to that depends on the shader, and each shader has a different set of string properties.

My question is, is there a way to get all the properties of a given shader so that I can iterate each one and check its value?


Edit: Alternatively, is there a place somewhere where I can find all the properties used by Unity's shaders? or the code of all those shaders so that I can extract a definitive list of all used property names?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by whydoidoit · Jan 28, 2013 at 06:37 PM

EDIT: As of 4.1 ShaderUtils is now a public documented class. You no longer need this code from that version of Unity onwards.

You can get them in an Editor script by using the hidden ShaderUtils class. I've written a wrapper which is a C# extension class for material allowing you to get the properties, their count, type and name. Plus useful stuff like all of the referenced textures.

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using UnityEditor;
 using UnityEngine;
 using System.IO;
 using System.Collections;
     
 public static class ShaderUtilInterface
 {
     public static Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();
 
     static ShaderUtilInterface()
     {
         var asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a=>a.GetTypes().Any(t=>t.Name == "ShaderUtil"));
         if(asm != null)
         {
             var tp = asm.GetTypes().FirstOrDefault(t=>t.Name == "ShaderUtil");
             foreach(var method in tp.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
             {
                 methods[method.Name] = method;
             }
         }
     }
     
     public static List<Texture> GetTextures(this Material shader)
     {
         var list = new List<Texture>();
         var count = shader.GetPropertyCount();
         for(var i = 0; i < count; i++)
         {
             if(shader.GetPropertyType(i)==4)
             {
                 list.Add((Texture)shader.GetProperty(i));
             }
         }
         return list;
     }
     
     public static int GetPropertyCount(this Material shader)
     {
         return Call<int>("GetPropertyCount", shader.shader);
     }
     
     public static int GetPropertyType(this Material shader, int index)
     {
         return Call<int>("GetPropertyType", shader.shader, index);
     }
     
     public static string GetPropertyName(this Material shader, int index)
     {
         return Call<string>("GetPropertyName", shader.shader, index);
     }
     
     public static void SetProperty(this Material material, int index, object value)
     {
         var name = material.GetPropertyName(index);
         var type = material.GetPropertyType(index);
         switch(type)
         {
         case 0:
             material.SetColor(name, (Color)value);
             break;
         case 1:
             material.SetVector(name, (Vector4) value);
             break;
         case 2:
             material.SetFloat(name, (float)value);
             break;
         case 3:
             material.SetFloat(name, (float)value);
             break;
         case 4:
             material.SetTexture(name, (Texture) value);
             break;
         }
     }
 
 
     
     public static object GetProperty(this Material material, int index)
     {
         var name = material.GetPropertyName(index);
         var type = material.GetPropertyType(index);
         switch(type)
         {
         case 0:
             return material.GetColor(name);
             
         case 1:
             return material.GetVector(name);
             
             
         case 2:
         case 3:
             return material.GetFloat(name);
             
         case 4:
             return material.GetTexture(name);
             
         }
     return null;
     }
     
     public static T Call<T>(string name, params object[] parameters)
     {
         return (T)methods[name].Invoke(null, parameters);
     }
 
 }
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Jan 28, 2013 at 06:39 PM 1
Share

Here's an example of using it:

    var materialTextures = new Dictionary< Texture, bool>();
     foreach (var m in all$$anonymous$$aterials)
     {
             foreach(var t in m.GetTextures())
             {
                 materialTextures[t] = false;
             }
     }

     var textureLookup = materialTextures.$$anonymous$$eys.Where(c=>!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(c))).GroupBy(c=>c.name).ToDictionary(c=>c.$$anonymous$$ey, c=>c.ToLookup(f=>new FileInfo(AssetDatabase.GetAssetPath(f)).Length));
     var usedTextures = new Dictionary();
     foreach(var m in all$$anonymous$$aterials)
     {
         for(var i = 0; i < m.GetPropertyCount(); i++)
         {
             if(m.GetPropertyType(i)==4)
             {
                 var currentTexture = m.GetProperty(i) as Texture;
                 if(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(currentTexture)))
                     continue;
                 var newTexture = textureLookup[currentTexture.name][new FileInfo(AssetDatabase.GetAssetPath(currentTexture)).Length].First();
                 m.SetProperty(i,newTexture);
                 materialTextures.Remove(newTexture);
                 usedTextures[newTexture] = true;
             }
         }
         EditorUtility.SetDirty(m);
     }
avatar image Bunny83 · Mar 22, 2013 at 09:35 AM 2
Share

Nice ;) just what i need. Well designed (except the magic "type-numbers" :D)

+1

ps: what's the difference between type 2 and 3? I mean inside the shader...

edit
Never$$anonymous$$d, got it ;)

 internal enum ShaderPropertyType
 {
     Color,
     Vector,
     Float,
     Range,
     TexEnv
 }
avatar image whydoidoit · Mar 22, 2013 at 09:41 AM 0
Share

It's range and float...

avatar image nicloay · Mar 27, 2013 at 11:57 AM 1
Share

Hey, whydoidoit thanks for you example, I found that shaderUtil class right now is open and api available here http://docs.unity3d.com/Documentation/ScriptReference/ShaderUtil.html just didn't find ShaderPropertyType, so thanks to Bunny83

and here is my implementation of the listTexturesBy$$anonymous$$aterial method

 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 using System.Collections.Generic;
 
 public class UFT$$anonymous$$aterialUtil {
     
     public static List<Texture> getTextures($$anonymous$$aterial material){
         string assetPath=AssetDatabase.GetAssetPath(material);        
         if (String.IsNullOrEmpty(assetPath))
             return null;
         Shader shader=material.shader;            
         List<Texture> materials=new List<Texture>();
         for (int i = 0; i < ShaderUtil.GetPropertyCount(shader) ; i++) {                
             if (ShaderUtil.GetPropertyType(shader,i) == ShaderUtil.ShaderPropertyType.TexEnv){
                 materials.Add(material.GetTexture(ShaderUtil.GetPropertyName(shader,i)));
             }            
         }
         return materials;
     }    
 }
 
avatar image whydoidoit · Mar 27, 2013 at 01:50 PM 0
Share

Yeah they opened it up in 4.1!

avatar image
5

Answer by amirabiri · Oct 23, 2011 at 02:11 PM

OK, I should have thought of the 2nd option myself first:

http://www.unity3d.com/support/resources/assets/built-in-shaders


Edit: For anyone reading this who is looking for the "definitive" list of the texture shader property of Unity's built-in properties:

 { "_BackTex", "_BumpMap", "_BumpSpecMap", "_Control", "_DecalTex",
   "_Detail", "_DownTex", "_FrontTex", "_GlossMap", "_Illum", "_LeftTex",
   "_LightMap", "_LightTextureB0", "_MainTex", "_ParallaxMap", "_RightTex",
   "_ShadowOffset", "_Splat0", "_Splat1", "_Splat2", "_Splat3",
   "_TranslucencyMap", "_UpTex", "_Tex", "_Cube" };

Note that this true as of right now, and could change if Unity's shaders change in the future.

This is the shell command I used to extract the property names:

 pcregrep -r -M 'Properties\s*{.*(\n.+)*\n}' -N anycrlf * | grep 2D | awk '{print $1}' | sort | uniq


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

How can I change default shader for new/imported objects? 1 Answer

Material doesn't have a color property '_Color' 4 Answers

Display material only in editor 2 Answers

Is it possible to change the shader the editor uses? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges