Hey!
I hope you guys will see this.
As I also wanted to add an outline to the standard shader, i had it working by adding the code from the āToonBasicOutlineā shader like this :
Shader "Standard (Outlined)" {
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
_MetallicGlossMap("Metallic", 2D) = "white" {}
_BumpScale("Scale", Float) = 1.0
_BumpMap("Normal Map", 2D) = "bump" {}
_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
_ParallaxMap ("Height Map", 2D) = "black" {}
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DetailMask("Detail Mask", 2D) = "white" {}
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
_DetailNormalMapScale("Scale", Float) = 1.0
_DetailNormalMap("Normal Map", 2D) = "bump" {}
[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
// UI-only data
[HideInInspector] _EmissionScaleUI("Scale", Float) = 0.0
[HideInInspector] _EmissionColorUI("Color", Color) = (1,1,1)
// Blending state
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
// -------------------------
// Added Outline properties
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline width", Range (.002, 0.03)) = .005
// -------------------------
}
CGINCLUDE
#define UNITY_SETUP_BRDF_INPUT MetallicSetup
ENDCG
/////////////////////////////////////////////////////////////////////////////////////////////
SubShader
{
Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
LOD 300
// ----------------------
// Start of Outline adding
CGINCLUDE
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
UNITY_FOG_COORDS(0)
fixed4 color : COLOR;
};
uniform float _Outline;
uniform float4 _OutlineColor;
v2f vert(appdata v) {
// just make a copy of incoming vertex data but scaled according to normal direction
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
ENDCG
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
fixed4 frag(v2f i) : SV_Target
{
UNITY_APPLY_FOG(i.fogCoord, i.color);
return i.color;
}
ENDCG
}
// End of Outline adding
// ----------------------
// ------------------------------------------------------------------
// Base forward pass (directional light, emission, lightmaps, ...)
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardBase" }
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma vertex vertForwardBase
#pragma fragment fragForwardBase
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Additive forward pass (one light per pass)
Pass
{
Name "FORWARD_DELTA"
Tags { "LightMode" = "ForwardAdd" }
Blend [_SrcBlend] One
Fog { Color (0,0,0,0) } // in additive pass fog should be black
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma target 3.0
// GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma multi_compile_fwdadd_fullshadows
#pragma multi_compile_fog
#pragma vertex vertForwardAdd
#pragma fragment fragForwardAdd
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma multi_compile_shadowcaster
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Deferred pass
Pass
{
Name "DEFERRED"
Tags { "LightMode" = "Deferred" }
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers nomrt gles
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma multi_compile ___ UNITY_HDR_ON
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
#pragma vertex vertDeferred
#pragma fragment fragDeferred
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Extracts information for lightmapping, GI (emission, albedo, ...)
// This pass it not used during regular rendering.
Pass
{
Name "META"
Tags { "LightMode"="Meta" }
Cull Off
CGPROGRAM
#pragma vertex vert_meta
#pragma fragment frag_meta
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#include "UnityStandardMeta.cginc"
ENDCG
}
}
SubShader
{
Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
LOD 150
// ------------------------------------------------------------------
// Base forward pass (directional light, emission, lightmaps, ...)
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardBase" }
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
CGPROGRAM
#pragma target 2.0
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
#pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma vertex vertForwardBase
#pragma fragment fragForwardBase
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Additive forward pass (one light per pass)
Pass
{
Name "FORWARD_DELTA"
Tags { "LightMode" = "ForwardAdd" }
Blend [_SrcBlend] One
Fog { Color (0,0,0,0) } // in additive pass fog should be black
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma target 2.0
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
#pragma skip_variants SHADOWS_SOFT
#pragma multi_compile_fwdadd_fullshadows
#pragma multi_compile_fog
#pragma vertex vertForwardAdd
#pragma fragment fragForwardAdd
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual
CGPROGRAM
#pragma target 2.0
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma skip_variants SHADOWS_SOFT
#pragma multi_compile_shadowcaster
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Extracts information for lightmapping, GI (emission, albedo, ...)
// This pass it not used during regular rendering.
Pass
{
Name "META"
Tags { "LightMode"="Meta" }
Cull Off
CGPROGRAM
#pragma vertex vert_meta
#pragma fragment frag_meta
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#include "UnityStandardMeta.cginc"
ENDCG
}
}
FallBack "Standard"
CustomEditor "CustomStandardShaderGUI"
}
Hereās the shader where I modified it (the rest is unchanged so I didnāt copy it all here).
And as you said, rev087, you canāt see the new properties in the inspector because of the custom editor made for the standard shader.
So I copied the āStandardShaderGUI.csā script and modified it to add the Outline properties.
Hereās what i got now :
using System;
using UnityEngine;
namespace UnityEditor
{
internal class CustomStandardShaderGUI : ShaderGUI
{
private enum WorkflowMode
{
Specular,
Metallic,
Dielectric
}
public enum BlendMode
{
Opaque,
Cutout,
Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency
Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
}
private static class Styles
{
public static GUIStyle optionsButton = "PaneOptions";
public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
public static string emptyTootip = "";
public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
public static GUIContent emissionText = new GUIContent("Emission", "Emission (RGB)");
public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
public static string whiteSpaceString = " ";
public static string primaryMapsText = "Main Maps";
public static string secondaryMapsText = "Secondary Maps";
public static string renderingMode = "Rendering Mode";
public static GUIContent emissiveWarning = new GUIContent ("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static GUIContent emissiveColorWarning = new GUIContent ("Ensure emissive color is non-black for emission to have effect.");
public static readonly string[] blendNames = Enum.GetNames (typeof (BlendMode));
}
MaterialProperty blendMode = null;
MaterialProperty albedoMap = null;
MaterialProperty albedoColor = null;
MaterialProperty alphaCutoff = null;
MaterialProperty specularMap = null;
MaterialProperty specularColor = null;
MaterialProperty metallicMap = null;
MaterialProperty metallic = null;
MaterialProperty smoothness = null;
MaterialProperty bumpScale = null;
MaterialProperty bumpMap = null;
MaterialProperty occlusionStrength = null;
MaterialProperty occlusionMap = null;
MaterialProperty heigtMapScale = null;
MaterialProperty heightMap = null;
MaterialProperty emissionScaleUI = null;
MaterialProperty emissionColorUI = null;
MaterialProperty emissionColorForRendering = null;
MaterialProperty emissionMap = null;
MaterialProperty detailMask = null;
MaterialProperty detailAlbedoMap = null;
MaterialProperty detailNormalMapScale = null;
MaterialProperty detailNormalMap = null;
MaterialProperty uvSetSecondary = null;
// Outline Add ------------------------------------------------------- //
MaterialProperty _OutlineColor = null;
MaterialProperty _Outline = null;
MaterialEditor m_MaterialEditor;
WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
bool m_FirstTimeApply = true;
public void FindProperties (MaterialProperty[] props)
{
blendMode = FindProperty ("_Mode", props);
albedoMap = FindProperty ("_MainTex", props);
albedoColor = FindProperty ("_Color", props);
alphaCutoff = FindProperty ("_Cutoff", props);
specularMap = FindProperty ("_SpecGlossMap", props, false);
specularColor = FindProperty ("_SpecColor", props, false);
metallicMap = FindProperty ("_MetallicGlossMap", props, false);
metallic = FindProperty ("_Metallic", props, false);
if (specularMap != null && specularColor != null)
m_WorkflowMode = WorkflowMode.Specular;
else if (metallicMap != null && metallic != null)
m_WorkflowMode = WorkflowMode.Metallic;
else
m_WorkflowMode = WorkflowMode.Dielectric;
smoothness = FindProperty ("_Glossiness", props);
bumpScale = FindProperty ("_BumpScale", props);
bumpMap = FindProperty ("_BumpMap", props);
heigtMapScale = FindProperty ("_Parallax", props);
heightMap = FindProperty("_ParallaxMap", props);
occlusionStrength = FindProperty ("_OcclusionStrength", props);
occlusionMap = FindProperty ("_OcclusionMap", props);
emissionScaleUI = FindProperty ("_EmissionScaleUI", props);
emissionColorUI = FindProperty ("_EmissionColorUI", props);
emissionColorForRendering = FindProperty ("_EmissionColor", props);
emissionMap = FindProperty ("_EmissionMap", props);
detailMask = FindProperty ("_DetailMask", props);
detailAlbedoMap = FindProperty ("_DetailAlbedoMap", props);
detailNormalMapScale = FindProperty ("_DetailNormalMapScale", props);
detailNormalMap = FindProperty ("_DetailNormalMap", props);
uvSetSecondary = FindProperty ("_UVSec", props);
// Outline Add ------------------------------------------------------- //
_OutlineColor = FindProperty ("_OutlineColor", props);
_Outline = FindProperty ("_Outline", props);
}
public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] props)
{
FindProperties (props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
ShaderPropertiesGUI (material);
// Make sure that needed keywords are set up if we're switching some existing
// material to a standard shader.
if (m_FirstTimeApply)
{
SetMaterialKeywords (material, m_WorkflowMode);
m_FirstTimeApply = false;
}
}
public void ShaderPropertiesGUI (Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
BlendModePopup();
// Primary properties
GUILayout.Label (Styles.primaryMapsText, EditorStyles.boldLabel);
DoAlbedoArea(material);
DoSpecularMetallicArea();
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
DoEmissionArea(material);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
EditorGUI.BeginChangeCheck();
m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
if (EditorGUI.EndChangeCheck())
emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
EditorGUILayout.Space();
// Secondary properties
GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
EditorGUILayout.Space();
// Outline properties --------------------------------------------------- //
GUILayout.Label ("Outline Properties", EditorStyles.boldLabel);
m_MaterialEditor.ColorProperty (_OutlineColor, "Outline Color");
m_MaterialEditor.FloatProperty (_Outline, "Outline Width");
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in blendMode.targets)
MaterialChanged((Material)obj, m_WorkflowMode);
}
}
internal void DetermineWorkflow(MaterialProperty[] props)
{
if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
m_WorkflowMode = WorkflowMode.Specular;
else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
m_WorkflowMode = WorkflowMode.Metallic;
else
m_WorkflowMode = WorkflowMode.Dielectric;
}
public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
return;
BlendMode blendMode = BlendMode.Opaque;
if (oldShader.name.Contains("/Transparent/Cutout/"))
{
blendMode = BlendMode.Cutout;
}
else if (oldShader.name.Contains("/Transparent/"))
{
// NOTE: legacy shaders did not provide physically based transparency
// therefore Fade mode
blendMode = BlendMode.Fade;
}
material.SetFloat("_Mode", (float)blendMode);
//DetermineWorkflow( ShaderUtil.GetMaterialProperties(new Material[] { material }) );
MaterialChanged(material, m_WorkflowMode);
}
void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
blendMode.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
void DoAlbedoArea(Material material)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
{
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel+1);
}
}
void DoEmissionArea(Material material)
{
bool showEmissionColorAndGIControls = emissionScaleUI.floatValue > 0f;
bool hadEmissionTexture = emissionMap.textureValue != null;
// Do controls
m_MaterialEditor.TexturePropertySingleLine(Styles.emissionText, emissionMap, showEmissionColorAndGIControls ? emissionColorUI : null, emissionScaleUI);
// Set default emissionScaleUI if texture was assigned
if (emissionMap.textureValue != null && !hadEmissionTexture && emissionScaleUI.floatValue <= 0f)
emissionScaleUI.floatValue = 1.0f;
// Dynamic Lightmapping mode
if (showEmissionColorAndGIControls)
{
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(EvalFinalEmissionColor(material));
EditorGUI.BeginDisabledGroup(!shouldEmissionBeEnabled);
m_MaterialEditor.LightmapEmissionProperty (MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
EditorGUI.EndDisabledGroup();
}
if (!HasValidEmissiveKeyword(material))
{
EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
}
}
void DoSpecularMetallicArea()
{
if (m_WorkflowMode == WorkflowMode.Specular)
{
if (specularMap.textureValue == null)
m_MaterialEditor.TexturePropertyTwoLines(Styles.specularMapText, specularMap, specularColor, Styles.smoothnessText, smoothness);
else
m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap);
}
else if (m_WorkflowMode == WorkflowMode.Metallic)
{
if (metallicMap.textureValue == null)
m_MaterialEditor.TexturePropertyTwoLines(Styles.metallicMapText, metallicMap, metallic, Styles.smoothnessText, smoothness);
else
m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
}
}
public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
{
switch (blendMode)
{
case BlendMode.Opaque:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case BlendMode.Cutout:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
case BlendMode.Fade:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case BlendMode.Transparent:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
}
}
// Calculate final HDR _EmissionColor (gamma space) from _EmissionColorUI (LDR, gamma) & _EmissionScaleUI (gamma)
static Color EvalFinalEmissionColor(Material material)
{
return material.GetColor("_EmissionColorUI") * material.GetFloat("_EmissionScaleUI");
}
static bool ShouldEmissionBeEnabled (Color color)
{
return color.grayscale > (0.1f / 255.0f);
}
static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
SetKeyword (material, "_NORMALMAP", material.GetTexture ("_BumpMap") || material.GetTexture ("_DetailNormalMap"));
if (workflowMode == WorkflowMode.Specular)
SetKeyword (material, "_SPECGLOSSMAP", material.GetTexture ("_SpecGlossMap"));
else if (workflowMode == WorkflowMode.Metallic)
SetKeyword (material, "_METALLICGLOSSMAP", material.GetTexture ("_MetallicGlossMap"));
SetKeyword (material, "_PARALLAXMAP", material.GetTexture ("_ParallaxMap"));
SetKeyword (material, "_DETAIL_MULX2", material.GetTexture ("_DetailAlbedoMap") || material.GetTexture ("_DetailNormalMap"));
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled (material.GetColor("_EmissionColor"));
SetKeyword (material, "_EMISSION", shouldEmissionBeEnabled);
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (!shouldEmissionBeEnabled)
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
}
}
bool HasValidEmissiveKeyword (Material material)
{
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (emissionColorForRendering.colorValue))
return false;
else
return true;
}
static void MaterialChanged(Material material, WorkflowMode workflowMode)
{
// Clamp EmissionScale to always positive
if (material.GetFloat("_EmissionScaleUI") < 0.0f)
material.SetFloat("_EmissionScaleUI", 0.0f);
// Apply combined emission value
Color emissionColorOut = EvalFinalEmissionColor (material);
material.SetColor("_EmissionColor", emissionColorOut);
// Handle Blending modes
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
SetMaterialKeywords(material, workflowMode);
}
static void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword (keyword);
else
m.DisableKeyword (keyword);
}
}
} // namespace UnityEditor
You can just copy and paste it in a new CS file, this will work (there are just a few added lines, might not be worth the scroll ^^).
After this, you need to change the last line of your modified Standard shader (the shader, not the .cs file) to this :
CustomEditor "CustomStandardShaderGUI"
Change your materialās shader to the new āStandard (Outlined)ā shader and this is it! The default Outline width is set to 0.005. I recommend you to keep it like this as I find it good but you can still try to set it differently (just donāt go too high as this will not work as intended).
Also, the āToonBasicOutlineā shader included in Unity may not be the best outline shader, but itās the best I could find. If you find another one, please let me know!