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 :)
Answer by Red-Works · Apr 08, 2019 at 03:10 AM
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;
}
}
}
}
Hi @polyworks,
Thanks a lot for your answer ! I don't have time to try it right now but I will get back to you when I test it.
Again thank you for taking the time
Allow me to say it with a famous quote: "Noooooooooo ..." -Darth Vader
Look for the answer by Undume further down. His or hers is the right way to do it in just 3 lines of code!
Though the above will probably work, it's just way too much code and only going to spell trouble if the Material/Shader doesn't have the properties that the code requires.
Answer by Undume · Feb 26, 2021 at 08:42 PM
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;
}
}
Answer by venomtail · Apr 02, 2019 at 12:01 AM
How did you get your question to be approved? I've been waiting for ages but nothing. How long did it take?
Your answer
Follow this Question
Related Questions
What does this button in the material preview window do? (lighting and shader troubles) 0 Answers
Same material looks different in different projects 2 Answers
Receive Shadow Mesh Renderer - Weird Effect 0 Answers
some sprites are turning transparent while using a normal map and others don't 0 Answers
How to show transparent PNG on a plane - without backfaces? 0 Answers