Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
0
Question by NeatWolf · Nov 22, 2019 at 10:47 AM · shadersspecularreplaceshader-replacementreplacement

How do I globally (per project) replace/edit the builtin Standard PBR (Metallic/Specular) shaders with custom ones?

Hi there!

I would like to make just a few little changes to the builtin shaders and... my game is almost ready for launch. So there are tons of scenes and materials already using the default PBR Metallic/Specular Shaders.

I also have other materials/shaders as well, and they have to stay that way.

I'd like to replace:

  • builtin Standard PBR -> custom Standard PBR

  • builtin Standard PBR (Specular) -> custom Standard PBR (specular)

I'm targeting mobile, OpenGL ES 3.0, gamma color space, forward rendering, Subtractive mode lightmaps.

I found some info about replacement shaders, but I guess it's not exactly what I'd love to obtain.

Is it even technically possible?

I'd like to avoid replacing over 100 of materials manually, unless you can suggest a tool to let me make such switch trivial (back and forth from builtin/custom)

I'm also open to other solutions which would allow to do basically the same.

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

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by xibanya · Dec 24, 2019 at 04:25 AM

as far as I can tell, you can't update the builtin Standard shader, but you CAN update the builtin CGincludes in C:\Program Files\wherever your editor install is\Editor\Data\CGIncludes (that isn't per-project though, it's everything on that editor version.) If your shaders use the same properties as the standard shader, you could update the CGincludes referenced by the Standard shader (eg, "UnityStandardCoreForward.cginc" to do your thing instead, but tbh I can't recommend doing something like this so close to shipping because it would probably initially break the hell out of all your other surface shaders (and possibly some of your frag shaders too!)

As far as mass-changing shaders on materials, here's my route (simplified for space and readability). I have an Editor Utilities class where I keep editor API helper methods, and in that class I put

 public static List<Material> GetMaterials()
     {
         var matFiles = GetFiles(GetSelectedPathOrFallback()).Where(s => s.Contains(".mat"));
 
         List<Material> toReturn = new List<Material>();
         foreach (string str in matFiles)
         {
             Material mat = (Material)AssetDatabase.LoadAssetAtPath(str, typeof(Material));
             if (mat != null && !toReturn.Contains(mat)) toReturn.Add(mat);
         }
         return toReturn;
     }

which returns a list of all materials in the currently selected directory in Assets. (if none is selected, it'll run the search of ALL your assets.)

this uses a great utility method that I didn't write,

 //https://gist.github.com/kimsama/ff69cca140468f92d755
 public static string GetSelectedPathOrFallback()
 {
     string path = "Assets";
 
     foreach (UnityObject obj in Selection.GetFiltered(typeof(UnityObject), SelectionMode.Assets))
     {
         path = AssetDatabase.GetAssetPath(obj);
         if (!string.IsNullOrEmpty(path) && File.Exists(path))
         {
             path = Path.GetDirectoryName(path);
             break;
         }
     }
     return path;
 }

Then have an editor window that creates a dictionary of the shaders you want to replace and the shaders you want to replace them with and use that to replace all the materials in the current directory. to avoid having half the answer be taken up by EditorGUI code, I'll show a hardcoded dictionary, but ideally you'd actually get the shaders from object fields.

 using UnityEngine;
 using UnityEditor;
 using System.Collections.Generic;
 using System;
 using System.Linq;
 public class ShaderStandardizer : EditorWindow
 {
 private Dictionary<Shader, Shader> toReplace = new Dictionary<Shader, Shader>();
         private bool initialized;
         [MenuItem("Tools/MyTools/Shader Replacer")]
         private static void OpenWindow()
         {
             GetWindow<ShaderStandardizer>().Show();
         }
         void InitializeDictionary()
         {
             if (!initialized)
             {
                 toReplace.Add(Shader.Find("Standard"), Shader.Find("MyStudio/Category/ShaderName"));
                 toReplace.Add(Shader.Find("Standard (Specular setup)"), Shader.Find("MyStudio/Category/OtherShaderName"));
                 toReplace.Add(Shader.Find("Legacy Shaders/Bumped Specular"), Shader.Find("MyStudio/OtherCategory/ShaderName"));
                 initialized = true;
             }
         }
         protected override void OnGUI()
         {
             InitializeDictionary();
             if (GUILayout.Button("Replace"))
             {
                 string path = MyEditorUtils.GetSelectedPathOrFallback();
                 if (path != "Assets" || EditorUtility.DisplayDialog(
                     "Search from root?",
                     "Searching all assets from root can potentially lock Unity. Proceed?",
                     "OK", "Cancel"))
                 {
                     List<Material> materials = MyEditorUtils.GetMaterials().FindAll(m => toReplace.Keys.Contains(m.shader));
                     string title = string.Format("Update {0} materials?", materials.Count);
                     string message = string.Format("This operation will update {0} materials in {1} and subfolders. Proceed?", materials.Count, path);
                     string report = "UPDATED";
                     if (EditorUtility.DisplayDialog(title, message, "OK", "Cancel"))
                     {
                         foreach (Material material in materials)
                         {
                             report += string.Format("\n{0} from {1} to {2}", AssetDatabase.GetAssetPath(material), material.shader.name, materials[material.shader].name);
                             material.shader = materials[material.shader];
                         }
                     }
                     //use System.IO to write the report to a text file or something
                 }
             }
         }
         protected void OnDisable()
         {
             Resources.UnloadUnusedAssets();
         }
 }

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

126 People are following this question.

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

Related Questions

SOLVED - String replace % with " in C# 1 Answer

shadertoy to unity,Shadertoy to unity 0 Answers

Why are Cubemaps and Specular highlights not equally blurry at the same Roughness / Glossyness value with standard pbr shader? 0 Answers

Shader Replacement for DepthNormals with custom HLSL Clipping 1 Answer

Replace GameObject with another GameObject 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