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
1
Question by Tudor · Mar 11, 2015 at 11:06 AM · shadermaterialruntimerenderercompile

Building a Unity 5 Standard Material at runtime

I know that with the new Unity5 standard material / standard shader, if you don't populate a field (for example Normal map) then the shader is compiled without Normalmap calculations, for efficiency.

What I'm fuzzy on is how does this work if you want to make a new standard material at runtime?

If I do a Material mat = new Material() and set its shader to Shader.Find("Standard"), and then proceed to assign an Albedo texture and a Heightmap texture, will then my build at runtime compile an efficient Standard Material?

What if I already have a Standard Material with a Heightmap, and then at runtime I decide to remove its Heightmap entirely; will the standard shader then recompile to the version that doesn't calculate heightmaps?

Does unity maintain an internal array of precompiled versions of the Standard Shader, one for each combination of features that can be turned on or off? Or do I have to compile shaders manually? don't think that's possible.

Thanks for any insight!

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

3 Replies

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

Answer by Tudor · Mar 26, 2015 at 12:22 PM

Alright, so thanks to Yanik I was able to research this properly.

Unity does compile a standard shader which holds "all combinations" or "variants" of features included in the standard material. It does this via the #pragma multi_compile and #pragma shader_feature directives. Read more on them on their manual page, especially the part about the "Difference between shader_feature and multi_compile".

These directives use keywords to determine what bits of shader will be used at runtime to render the object. (e.g.: #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON)

You can then specify which of these elements you want to use, with the Shader.EnableKeyword("") and Shader.DisableKeyword(""), like Yanik said.

However, if the shader is using shader_feature as opposed to multi_compile, then the unused variants of shader_feature will not be included into your game Build.

I had a quick look at unity5's new standard shader source code and I see that it uses shader_feature a lot. I haven't tested this yet but it must mean that you must make a build where you have one dummy object with a standard material using all the features you will require at runtime, in order for the full shader to make it into the build.

[EDIT] As Cherro pointed out linking to the unity forums post, when you do:

 Material newMat = new Material(Shader.Find("Standard"));
 newMat.CopyPropertiesFromMaterial(dummyObjMat); 

the newMat, by default will have all the properties disabled, even though the shader variants -were- included in the build, and dummyObjMat was using them. So to activate them, simply use:

 newMat.EnableKeyword("_NORMALMAP"); //etc.


Comment
Add comment · Show 2 · 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 Cherno · Apr 05, 2015 at 12:47 AM 1
Share

Hey, thanks for the info. Did you have any success yet? I have the same problem, I want to create a runtime material and assign it a normal map, but the normal map only becomes visible in the game/editor view once ithe material is expanded/rolled out in the inspector (after assigning it to a gamneobject). Sadly, I ahve no experience with writing or modifying shaders at all, I took a look at the Standard shader source code and it had lines like

 #pragma shader_feature _NOR$$anonymous$$AL$$anonymous$$AP 

which according to the manual would mean that it gets included in the compiling process, right? Well, I guess I was wrong because I can'T figure out how to make it work :(`

Edit: The solution is in this thread:

link

avatar image Tudor · Apr 07, 2015 at 08:51 AM 0
Share

#pragma shader_feature _NOR$$anonymous$$AL$$anonymous$$AP means it only gets compiled into the build if there was a material in the scene which used a Normalmap. #pragma multi_compile _NOR$$anonymous$$AL$$anonymous$$AP would make sure all combinations including Normalmaps will be included no matter what, regardless if you ever need them or not. But as was pointed out in your forum link, it's best to use shader feature with the described method.

Also thanks for finding that forum post!

avatar image
1

Answer by yanik · Mar 25, 2015 at 06:26 PM

Hi. The material have to disable the keyword for heightmap :

material.DisableKeyword("_NORMALMAP");

Comment
Add comment · Show 1 · 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 Tudor · Mar 26, 2015 at 12:02 PM 0
Share

Thanks for that. It pointed me in the right direction. I'm, gonna elaborate on it though as it's not as easy as it sounds.

avatar image
1

Answer by saulth · Jul 06, 2017 at 11:50 PM

The comprehensive way to do this is to use the code written by Unity that is executed when you make changes to the material in the Editor. The code is available in the builtin_shaders-XXX.zip file (available for download from https://unity3d.com/get-unity/download/archive). Then, open up the Editor/StandardShaderGUI.cs file and copy out the five functions at the bottom (SetupMaterialWithBlendMode, GetSmoothnessMapChannel, SetMaterialKeywords, MaterialChanged, SetKeyword). Also copy the enums at the top of the class (WorkflowMode, BlendMode, SmoothnessMapChannel) and put in your own class. Then you want to call MaterialChanged() with the WorkflowMode.Metallic on your Material that you modified. Works identically to in-Editor changes :).

Comment
Add comment · Show 1 · 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 Taylor-Libonati · May 25, 2018 at 06:50 PM 0
Share

Thanks for this! It helped me get a dynamic material editor working.

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

24 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

Related Questions

Changing two different objects renderer colour 1 Answer

Changing Emission Scale UI with Script 0 Answers

Rendering an entire object as transparent 1 Answer

Cannot change material on build 1 Answer

How Do I Partially Change The Material of An Object On Collision? 1 Answer


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