Search Unity

Question Can shader graph materials properties be edited locally in each isntance of the material?

Discussion in 'Shader Graph' started by Acre94, Apr 22, 2019.

  1. Acre94

    Acre94

    Joined:
    May 30, 2016
    Posts:
    4
    Hello ! I am using shader graph for creating a toon shader. I am creating a library of basic colors that are used for different characters across scenes. I created a property called "lightColor" that affects the basic hue of the color (and makes the colors integrated with the scene colors), and hoped to be able to edit this locally, so that I don't have to create copies of the material for each light color variation I have.

    I am not a programmer, and I am very new to shader graph, so I am probably approaching this incorrectly. I would like to know how to edit properties inside materials from shader graph locally, so they don't affect the main material (and therefore all other characters using these colors). If this is impossible, could I maybe create a code that connects the scene's main light color to the property created inside the shader?

    Should I maybe work with albedo maps, and have materials for each type of character in the game, rather than having a library of colors that work on all objects in the game?

    Thanks for the patience !!

    upload_2019-4-22_11-36-56.png
     
  2. sanbox

    sanbox

    Joined:
    Oct 22, 2018
    Posts:
    5
    Hiya! I'm not exactly sure I understand. If you want to have a "Toon_Red" and a "Toon_Yellow", you'd want to make a different material for each color. That's the most performant and simplest answer.

    HOWEVER, if you want to be able to have any color and you want to change what the color is at Runtime, so that renderer A and renderer B, who share Material C, have different properties (ie. different colors on the material, despite sharing a material) you want what's called a "Material Property Block".

    https://docs.unity3d.com/ScriptReference/MaterialPropertyBlock.html
     
    Acre94 likes this.
  3. Acre94

    Acre94

    Joined:
    May 30, 2016
    Posts:
    4
    Hey !! I have materials with a basic color property, that is static, but I have a lightColor property, that should change in different scenes, and that affects how the color looks (in the image attached characters are tinted red because of this property). All of these are in the material settings (as the material cannot read the light color settings), and my problem is that in other scenes in which I am using the same colors for other characters, light Color is changed to whatever I have set previously, so I cannot have different light Color settings for the same materials in different scenes.

    Making duplicates for all possible scenarios seems doable but unpractical.

    Material property blocks seems exactly what I need, but unfortunately they also seem to be a source of more problems (I saw that adding them to shaders is fairly easy, but then the properties added need to be changed by code, which is something I have no idea how to do. Also, compiling the shader graphs and trying to make sense of anything inside the shader seems impossible)

    Are these property blocks usable with shader graphs?

    Where should I stablish the variables I want to be blocked? (as the code inside the graph is a constant repeating structure, and then random code) and would I need necessarily another code to make the changes?

    upload_2019-4-23_13-29-26.png

    (90% of the shader graph compiled code is this)
     
  4. sanbox

    sanbox

    Joined:
    Oct 22, 2018
    Posts:
    5
    Heya! So yeah, material property blocks require some C# knowledge, unfortunately. they're not too hard to set up though!

    The Material Property block references the Properties in the Blackboard of your Shader Graph. Specifically, if you look into your Blackboard under each property there's a thing called "Reference" which is normally set to kinda random stuff. Change that to something more human readable if you'd like, and then addressing it in C# isn't too hard.

    For example:

    If you have a Blackboard property called "Tint" and its Reference is "_Tint" you make a property like this:


    Code (CSharp):
    1.  
    2. public class SetColorBehaviour: Monobehaviour { // default unity class for everything
    3. // by adding this, it will show up in the inspector
    4. [SerializeField] Color MyColor = new Color();
    5.  
    6. void Start() {
    7. MaterialPropertyBlock myMatBlock = new MaterialPropertyBlock();
    8. myMatBlock.SetColor("_Tint", MyColor);
    9.  
    10. // Get our Renderer here...
    11. MeshRenderer myMeshRenderer = GetComponent<MeshRenderer>();
    12. myMeshRenderer.SetPropertyBlock(myMatBlock);
    13. }
    14. }
    apologies for the poor formatting of the code -these forums don't have great formatting.

    If all of that seems too complicated and weird to you, feel ABSOLUTELY fine to just make a new material for every new thing that you want, but those are basically your two options! It's also worth pointing out, making a new material is probably more performant than the material property block option (though it doesn't really matter)
     
    Jeremy-Borton and Acre94 like this.
  5. Acre94

    Acre94

    Joined:
    May 30, 2016
    Posts:
    4
    Thats great to know! I will have it in mind, and probably move forward with the duplicates option, as variations are not that many nor important. But I think I understood, it's a piece of code you attach to the object and not to the shader code (as I previously thought). I will definitely try it ! :D
     
  6. malte_unity753

    malte_unity753

    Joined:
    Jul 21, 2020
    Posts:
    1
    Thank you!