Change surface type with LWRP

Hi everyone,

I’m using LWRP and I would like to make some parts of my model become slightly transparent. In the editor, all I have to do is to change Surface Type from opaque to transparent and then the alpha of Albedo to 50 for example.

Now, I want to do the same thing in code. Is there a way to do this ? If yes, which is it ?
Please let me know if you need more info!

Thanks a lot for your help :slight_smile:

This question has a long answer, unfortunately. I can not find a shortcut for this. So I search deep into LWRP scripts and found this solution and write this code. It worked for me for now, I hope it works for you.

using UnityEngine;
using System;

public class DisplayController : MonoBehaviour
{
    public enum SurfaceType
    {
        Opaque,
        Transparent
    }

public enum BlendMode
{
    Alpha,
    Premultiply,
    Additive,
    Multiply
}

public Material wallMaterial;


public void ChangeWallTransparency(bool transparent)
{
    if (transparent)
    {
        wallMaterial.SetFloat("_Surface", (float)SurfaceType.Transparent);
        wallMaterial.SetFloat("_Blend", (float)BlendMode.Alpha);
    }
    else
    {
        wallMaterial.SetFloat("_Surface", (float)SurfaceType.Opaque);
    }
    SetupMaterialBlendMode(wallMaterial);
}

void SetupMaterialBlendMode(Material material)
{
    if (material == null)
        throw new ArgumentNullException("material");

    bool alphaClip = material.GetFloat("_AlphaClip") == 1;
    if (alphaClip)
        material.EnableKeyword("_ALPHATEST_ON");
    else
        material.DisableKeyword("_ALPHATEST_ON");

    SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
    if (surfaceType == 0)
    {
        material.SetOverrideTag("RenderType", "");
        material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
        material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
        material.SetInt("_ZWrite", 1);
        material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
        material.renderQueue = -1;
        material.SetShaderPassEnabled("ShadowCaster", true);
    }
    else
    {
        BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
        switch (blendMode)
        {
            case BlendMode.Alpha:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                material.SetShaderPassEnabled("ShadowCaster", false);
                break;
            case BlendMode.Premultiply:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                material.SetShaderPassEnabled("ShadowCaster", false);
                break;
            case BlendMode.Additive:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                material.SetShaderPassEnabled("ShadowCaster", false);
                break;
            case BlendMode.Multiply:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                material.SetShaderPassEnabled("ShadowCaster", false);
                break;
        }
    }
}
}

You can’t change in runtime the surface type to transparent in urp/lwrp, when you do it from the inspector during play mode, the editor is cheating so you can play with it and after do it properly.

The right thing to do is have a material with the transparency already set up. Then you copy the properties from the opaque to the transparent with Material.CopyPropertiesFromMaterial and pass the transparent reference to the render.

public class Item : Monobehaviour
{
       public Material transparentMaterial;
       
       private void SetModeTransparent()
       {
              MeshRenderer renderer = GetComponent<MeshRenderer>();
              Material originalMat = renderer.sharedMaterial;
              Material materialTrans = new Material(transparentMaterial);
              materialTrans.CopyPropertiesFromMaterial(originalMat);
              renderer.sharedMaterial = materialTrans;
       }
}

Anyone ? :slight_smile:

How did you get your question to be approved? I’ve been waiting for ages but nothing. How long did it take?

Anyone finding this in modern times, if you’re using ShaderGraph you MUST check “Allow Material Override” this will expose the built in properties and allow you to change them from code (like someMaterial.SetFloat("_AlphaClip", 1f)

If you want to see the properties available, you can just select the shadergraph asset, look in the inspector and scroll down the bottom of the “Properties” section.