Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Change Standard Shader Render Mode in Runtime

Discussion in 'Shaders' started by lmbarns, Apr 14, 2015.

  1. lmbarns

    lmbarns

    Joined:
    Jul 14, 2011
    Posts:
    1,628
    Only way I can get this working is to use 2 materials and just lerp between them, to change an object from opaque to transparent.

    Unity 5.0.1f1

    Code (CSharp):
    1. void Start () {
    2.         _ren = GetComponent<Renderer>();
    3.         _mat = _ren.material;
    4.         _control = _mat.color;
    5.         _control.a = 1;
    6.         _mat.color = _control;
    7.         _mat.SetFloat ("_Mode", 0);
    8.         print (_mat.GetFloat("_Mode"));  //prints 0
    9.         Invoke ("MakeTransparent", 5);
    10.     }
    11.  
    12.     void MakeTransparent(){
    13.         _control.a = 0.2f;
    14.         _mat.color = _control;
    15.         _mat.SetFloat ("_Mode", 3);
    16.         print (_mat.GetFloat("_Mode")); //prints 3 but the shader doesn't change in game
    17.     }
    If I start in transparent mode, the MakeTransparent function does change the alpha and such, but if it starts opaque it stays opaque in runtime even if the alpha is set to 0, the mode isn't refreshing when it's changed...

    How do I call .WarmUp() on a material? Er, how do I get the reference to
    ShaderVariantCollection.WarmUp
     
    Last edited: Apr 14, 2015
  2. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    If you open the StandardShaderGUI.cs (that you can find in the Editor folder of the builtin_shader archive) you will see that changing mode on standard shader is actually doing more thing :


    Code (CSharp):
    1. switch (blendMode)
    2.         {
    3.             case BlendMode.Opaque:
    4.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    5.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    6.                 material.SetInt("_ZWrite", 1);
    7.                 material.DisableKeyword("_ALPHATEST_ON");
    8.                 material.DisableKeyword("_ALPHABLEND_ON");
    9.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    10.                 material.renderQueue = -1;
    11.                 break;
    12.             case BlendMode.Cutout:
    13.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    14.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    15.                 material.SetInt("_ZWrite", 1);
    16.                 material.EnableKeyword("_ALPHATEST_ON");
    17.                 material.DisableKeyword("_ALPHABLEND_ON");
    18.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    19.                 material.renderQueue = 2450;
    20.                 break;
    21.             case BlendMode.Fade:
    22.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
    23.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    24.                 material.SetInt("_ZWrite", 0);
    25.                 material.DisableKeyword("_ALPHATEST_ON");
    26.                 material.EnableKeyword("_ALPHABLEND_ON");
    27.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    28.                 material.renderQueue = 3000;
    29.                 break;
    30.             case BlendMode.Transparent:
    31.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    32.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    33.                 material.SetInt("_ZWrite", 0);
    34.                 material.DisableKeyword("_ALPHATEST_ON");
    35.                 material.DisableKeyword("_ALPHABLEND_ON");
    36.                 material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
    37.                 material.renderQueue = 3000;
    38.                 break;
    39.         }
    _Mode is only here to design which mode the material is in, but have no effect on the code of said shader.

    Not sure about your last question thought... Are you asking on what to call WarmUp? You need a reference to a Shader Variant Collections (it's a type of asset you can create in the editor) and callm WarmUp on that.
     
  3. Sparrowfc

    Sparrowfc

    Joined:
    Jan 31, 2013
    Posts:
    100
    Check the Standard.shader in builtin shaders. There's two things you need to do. First in your shader you should write like this
    Code (CSharp):
    1. Properties
    2. {
    3.   ....//your shader's property
    4.   [HideInInspector]_SrcBlend ("", Float) = 1
    5.   [HideInInspector]_DstBlend ("", Float) = 0
    6. }
    7.  
    8. SubShader
    9. {
    10.     Tag {"Queue"="Opaque"}
    11.     Blend [_SrcBlend] [_DstBlend]
    12.  
    13.     ....//your shader code
    14. }
    this shader for default is opaque. when you need it to be transparent :
    Code (CSharp):
    1. material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
    2. material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    3. material.renderQueue = 3000;
    when you need it back to opaque :
    Code (CSharp):
    1. material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    2. material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    3. material.renderQueue = -1;
     
    e45240, hungrybelome and forestrf like this.
  4. aamine060

    aamine060

    Joined:
    Dec 31, 2017
    Posts:
    2
    Hi thanks


    could you tell me where should i put the second and third script? (on a new C# script and add it to the gameobject or add the two scripts to the same shader as the first script
     
  5. Sparrowfc

    Sparrowfc

    Joined:
    Jan 31, 2013
    Posts:
    100
    You can put it in anywhere. I'm guessing u don't know how to get the material variable. It's like first you get the GameObject you want to change, and then get the Renderer component and get the material attribute.
    Code (CSharp):
    1. GameObject g = GameObject.Find("XXXX");
    2. Renderer r = g.GetComponentInChildren<Renderer>();
    3. Material material = r.material;
    4.  
    5. //..modify the material..
     
  6. aamine060

    aamine060

    Joined:
    Dec 31, 2017
    Posts:
    2
    Thanks man i appreciate that
     
  7. DonPuno

    DonPuno

    Joined:
    Dec 22, 2020
    Posts:
    57

    Many thanks! It helped me a lot for solving the issue I was facing. It's a pity that until now there's no specific API-Call.
     
    e45240 likes this.
  8. ofirudwork

    ofirudwork

    Joined:
    Nov 3, 2021
    Posts:
    17
    How can I change the material render mode via code, but at Editor and not at runtime