Search Unity

Question How to manipulate a shader graph enum using C#?

Discussion in 'Shader Graph' started by ninthtale, Aug 20, 2023.

  1. ninthtale

    ninthtale

    Joined:
    Jan 23, 2018
    Posts:
    17
    I have a component whose function is to control various artistic expressions of a material, but is not itself an object with that material.

    What I want is an enum with various blending modes as a dropdown list, but I'm not sure how to make the code communicate with shader graph in the same way you can with global properties.

    So firstly, this is what I want: a dropdown list that represents the Enum property from the shader graph:
    upload_2023-8-20_16-27-12.png

    Except not exposed on the material itself, but on a separate controller object in the scene.

    This is easy with floats, integers, vectors, colors, etc., as they all have predefined Shader.SetGlobal____ properties that can be called as long as you have a node with the corresponding reference ID.

    Enum, on the other hand, apparently cannot be converted to a float or an integer. An Enum's list has corresponding integer values, though, so this is counterintuitive to me.

    This is the code I have right now. It creates the dropdown (like in the image above) but even though I've given it the correct Reference ID _EDGEGLOWBLENDINGMODE, it doesn't seem to communicate at all with that shader graph node. I've trimmed out the unrelated portions:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [ExecuteInEditMode]
    6.  
    7. public class Interactor : MonoBehaviour
    8. {  
    9.  
    10.     [SerializeField]
    11.  
    12.     [Header("Edge Blending")]
    13.  
    14.     public Material edgeGlowMaterial;
    15.     public enum BlendingMode
    16.     {
    17.         Multiply,
    18.         Add,
    19.         SubA,
    20.         SubB
    21.     }
    22.    
    23.     public BlendingMode blendingMode;
    24.    
    25.  
    26.     private void Start()
    27.     {
    28.         int blendingModeIndex = (int)blendingMode;
    29.         edgeGlowMaterial.SetInt("_EDGEGLOWBLENDINGMODE", blendingModeIndex);
    30.     }
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.        
    35.     }
    36. }
    I think I know why this is not working: the sort of tutorial I followed just trying to get the dropdown to appear is requiring the definition of a material at line 14; the SetInt command on line 29 is trying to set the properties of that material, which is really just irrelevant here.

    But yeah, I don't know what I would need to do to connect the dropdown to the actual enum node in the shader graph. I don't know if my logic is just backwards, or if this is even possible at all..
     
  2. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,315
  3. ninthtale

    ninthtale

    Joined:
    Jan 23, 2018
    Posts:
    17
    Like you said, I don't think there is a way to use Int, so I'm trying to find out how I can connect my drop down list to the enum keyword via the script..

    Your link to the documentation looks promising, but it's not terribly descriptive, and seems to assume a level that's yet way over my head..
     
  4. axlvc

    axlvc

    Joined:
    Mar 18, 2022
    Posts:
    1
    as it says here https://docs.unity3d.com/Packages/com.unity.shadergraph@12.0/manual/Keywords.html, you need to use
    Material
    |
    Shader.EnableKeyword({REFERENCE}_{REFERENCESUFFIX})
    .

    upload_2023-11-5_19-44-25.png
    In this case, the Reference is
    _Enum
    and the Reference Suffixes are
    A
    ,
    B
    , and
    C
    . So the Keywords are
    _Enum_A
    ,
    _Enum_B
    , and
    _Enum_C
    .
    What worked for me is to first disable the default keyword and then enabling the option you want form the enum.
    Code (CSharp):
    1. Material.DisableKeyword("_Enum_A");
    2. switch (OptionToEnable) {
    3.     case 0:
    4.         Material.EnableKeyword("_Enum_A");
    5.         break;
    6.     case 1:
    7.         Material.EnableKeyword("_Enum_B");
    8.         break;
    9.     case 2:
    10.         Material.EnableKeyword("_Enum_C");
    11.         break;
    12. }
    Seeing how this question was asked all the way back in 2018, I'm probably just a little bit late with this response. But I hope this answer might help people finding this in the future.
     

    Attached Files:

    Pierre_L_F likes this.
  5. badjano

    badjano

    Joined:
    Aug 2, 2012
    Posts:
    25
    I had some problems enabling a global keyword, so if anyone is having the same issue, you need to disable the other enums, this is my code:

    Code (CSharp):
    1.                
    2.                var qualities = Enum.GetValues(typeof(Quality));
    3.  
    4.                 foreach (Quality quality in qualities)
    5.                 {
    6.                     var keyword = "_QUALITYLEVEL_" + quality.ToString().ToUpper();
    7.  
    8.                     if (quality == newQuality)
    9.                         Shader.EnableKeyword(keyword);
    10.                     else
    11.                         Shader.DisableKeyword(keyword);
    12.                 }
    13.  
    Remember to use REFERENCE names, not names