Search Unity

Question How can I expose 'Surface Type' in shader graph

Discussion in 'Shader Graph' started by hawaiian_lasagne, Apr 5, 2020.

  1. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    123
    Hi

    The Universal Render Pipeline/Lit shader has a 'Surface Type' property for making something transparent/opaque. In shader graph, it only seems possible to set this directly on the PBR master node.

    Is it possible to add this to the blackboard somehow to expose it?
     
    The_Swiss_Guy likes this.
  2. spiegelball

    spiegelball

    Joined:
    Mar 2, 2020
    Posts:
    16
    You can set this via .SetInt("_SurfaceType", ...) without manual exposing per material. Note that you also have to set the render queue accordingly.

    Transparent:
    .SetInt("_SurfaceType", 1);
    .SetInt("_RenderQueueType", 4);

    Opaque:
    .SetInt("_SurfaceType", 0);
    .SetInt("_RenderQueueType", 1);

    Edit: I don't remember how I figured out which are the right numbers. Maybe debugging...
     
    hawaiian_lasagne likes this.
  3. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    123
    Thank you this worked perfectly!
     
  4. spiegelball

    spiegelball

    Joined:
    Mar 2, 2020
    Posts:
    16
    I just discovered that in my case A LOT more shader flags have to be set and that only the transparent -> opaque conversion worked with the subset of flags shared earlier.

    Transparent:
    Code (CSharp):
    1. transparentMat.EnableKeyword("_BLENDMODE_ALPHA");
    2. transparentMat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
    3. transparentMat.EnableKeyword("_ENABLE_FOG_ON_TRANSPARENT");
    4. transparentMat.DisableKeyword("_BLENDMODE_ADD");
    5. transparentMat.DisableKeyword("_BLENDMODE_PRE_MULTIPLY");
    6.  
    7. transparentMat.SetFloat("_SurfaceType", (int)SurfaceType.Transparent);
    8. transparentMat.SetFloat("_RenderQueueType", 5);
    9. transparentMat.SetFloat("_BlendMode", 0);
    10. transparentMat.SetFloat("_AlphaCutoffEnable", 0);
    11. transparentMat.SetFloat("_SrcBlend", 1f);
    12. transparentMat.SetFloat("_DstBlend", 10f);
    13. transparentMat.SetFloat("_AlphaSrcBlend", 1f);
    14. transparentMat.SetFloat("_AlphaDstBlend", 10f);
    15. transparentMat.SetFloat("_ZTestDepthEqualForOpaque", 4f);
    16.  
    17. transparentMat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
    Opaque:
    Code (CSharp):
    1. opaqueMat.SetInt("_SurfaceType"_STRING, (int)SurfaceType.Opaque);
    2. opaqueMat.SetInt("_RenderQueueType", (int)1);
    3. opaqueMat.SetFloat("_AlphaDstBlend", 0f);
    4. opaqueMat.SetFloat("_DstBlend", 0f);
    5. opaqueMat.SetFloat("_ZTestDepthEqualForOpaque", 3f);
    6. opaqueMat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
     
    Last edited: Apr 14, 2020
  5. youngjinna97

    youngjinna97

    Joined:
    Nov 23, 2020
    Posts:
    2
    Code (CSharp):
    1. void ViewObstructed()
    2.     {
    3.         RaycastHit hit;
    4.         if(Physics.Raycast(transform.position, target.position - transform.position, out hit))
    5.             if(hit.collider.gameObject.name != HitObj)
    6.             {
    7.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetInt("_SurfaceType", 0);
    8.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetFloat("Vector1_2B798094", 1f);
    9.             }
    10.  
    11.             if(hit.collider.gameObject.tag != "Player")
    12.             {
    13.                 Obstruction = hit.transform;
    14.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetInt("_SurfaceType", 1);
    15.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetFloat("Vector1_2B798094", 0.3f);
    16.                 HitObj = hit.collider.gameObject.name;
    17.             }
    18.             else
    19.             {
    20.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetInt("_SurfaceType", 0);
    21.                 Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetFloat("Vector1_2B798094", 1f);
    22.             }
    23.         }
    24.     }
    Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetInt("_SurfaceType", 0);
    it's for Opaque surface of PBR Master.

    Obstruction.gameObject.GetComponent<MeshRenderer>().material.SetInt("_SurfaceType", 1);
    it's for Transparent surface of PBR Master.

    but i dont know it doesnt work.. please help me..
     
    hawaiian_lasagne likes this.
  6. youngjinna97

    youngjinna97

    Joined:
    Nov 23, 2020
    Posts:
    2
    ohh,, of course i also add it too..
    Obstruction.gameObject.GetComponent<MeshRenderer>().material..SetInt("_RenderQueueType", 4);
    Obstruction.gameObject.GetComponent<MeshRenderer>().material..SetInt("_RenderQueueType", 1);
     
    hawaiian_lasagne likes this.
  7. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    123
  8. Helaly96

    Helaly96

    Joined:
    Mar 29, 2020
    Posts:
    8
    this didn't work for me at all
     
  9. Helaly96

    Helaly96

    Joined:
    Mar 29, 2020
    Posts:
    8
    these do get changed but they have no effect
     
  10. binoman

    binoman

    Joined:
    Sep 29, 2016
    Posts:
    13
    I must be missing something. Sorry for my n00bness, but you're all talking about code where the Shader graph is, well, a graph tool for shaders. What am I missing? where do you implement the code you all talk about?
     
    ddabble likes this.
  11. magique

    magique

    Joined:
    May 2, 2014
    Posts:
    4,030
    I don't when this might have changed, but I tried this in Unity 2021 and there was no such value as _SurfaceType, but if you change it to _Surface then it works.
     
  12. gwelkind

    gwelkind

    Joined:
    Sep 16, 2015
    Posts:
    66
    I missed this at first too. He's saying instead of setting this in ShaderGraph as a variable, you don't need to do this, because ALL URP materials have these variables dynamically defined.

    i.e., why would we want a variable? So we can change it in C#, right? Well, we can change it in C# without declaring a variable.
     
  13. gwelkind

    gwelkind

    Joined:
    Sep 16, 2015
    Posts:
    66
    I made a new solution for this problem for a custom shader graph built on lit.

    What I've done to solve the problem, which feels a bit more reliable to me, is just to make two shaders (one transparent, one opaque), then, when I need to toggle at runtime (or from within the materials editor) I just do `material.shader = Shader.Find("Transparent_counterpart")`

    All of the prop values get transferred seamlessly, and, presumably, this will work across versions. I think it should be the recommended method, even though it creates some duplicate code/graph.