Search Unity

Question How do I add Emmission from the Outline code? Help me...

Discussion in 'Shaders' started by Junhong_Min, Mar 10, 2023.

  1. Junhong_Min

    Junhong_Min

    Joined:
    Feb 17, 2022
    Posts:
    2
    Quick Outline code, a free Unity Asset. I want to change it to a color with an Emission effect,
    but I don't know how to fix it. Help me.
    I've tried many things, such as multiplying the value of the color or adding _EmissionColor, but I've made a mishap with only white colors. It seems like a simple problem, but as a beginner, it is hard to approach.

    ------------------------------------------------------------------------------------------------------------------------------------------


    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine;
    5.  
    6. [DisallowMultipleComponent]
    7.  
    8. public class Outline : MonoBehaviour {
    9.   private static HashSet<Mesh> registeredMeshes = new HashSet<Mesh>();
    10.  
    11.   public enum Mode {
    12.     OutlineAll,
    13.     OutlineVisible,
    14.     OutlineHidden,
    15.     OutlineAndSilhouette,
    16.     SilhouetteOnly
    17.   }
    18.  
    19.   public Mode OutlineMode {
    20.     get { return outlineMode; }
    21.     set {
    22.       outlineMode = value;
    23.       needsUpdate = true;
    24.     }
    25.   }
    26.  
    27.   public Color OutlineColor {
    28.     get { return outlineColor; }
    29.     set {
    30.       outlineColor = value;
    31.       needsUpdate = true;
    32.     }
    33.   }
    34.  
    35.   public float OutlineWidth {
    36.     get { return outlineWidth; }
    37.     set {
    38.       outlineWidth = value;
    39.       needsUpdate = true;
    40.     }
    41.   }
    42.  
    43.   [Serializable]
    44.   private class ListVector3 {
    45.     public List<Vector3> data;
    46.   }
    47.  
    48.   [SerializeField]
    49.   private Mode outlineMode;
    50.  
    51.   [SerializeField]
    52.   private Color outlineColor = Color.white;
    53.  
    54.   [SerializeField, Range(0f, 20f)]
    55.   private float outlineWidth = 2f;
    56.  
    57.   [Header("Optional")]
    58.  
    59.   [SerializeField, Tooltip("Precompute enabled: Per-vertex calculations are performed in the editor and serialized with the object. "
    60.   + "Precompute disabled: Per-vertex calculations are performed at runtime in Awake(). This may cause a pause for large meshes.")]
    61.   private bool precomputeOutline;
    62.  
    63.   [SerializeField, HideInInspector]
    64.   private List<Mesh> bakeKeys = new List<Mesh>();
    65.  
    66.   [SerializeField, HideInInspector]
    67.   private List<ListVector3> bakeValues = new List<ListVector3>();
    68.  
    69.   private Renderer[] renderers;
    70.   private Material outlineMaskMaterial;
    71.   private Material outlineFillMaterial;
    72.  
    73.   private bool needsUpdate;
    74.  
    75.   void Awake() {
    76.  
    77.     renderers = GetComponentsInChildren<Renderer>();
    78.  
    79.     outlineMaskMaterial = Instantiate(Resources.Load<Material>(@"Materials/OutlineMask"));
    80.     outlineFillMaterial = Instantiate(Resources.Load<Material>(@"Materials/OutlineFill"));
    81.  
    82.     outlineMaskMaterial.name = "OutlineMask (Instance)";
    83.     outlineFillMaterial.name = "OutlineFill (Instance)";
    84.  
    85.     LoadSmoothNormals();
    86.  
    87.     needsUpdate = true;
    88.   }
    89.  
    90.   void OnEnable() {
    91.     foreach (var renderer in renderers) {
    92.  
    93.       var materials = renderer.sharedMaterials.ToList();
    94.  
    95.       materials.Add(outlineMaskMaterial);
    96.       materials.Add(outlineFillMaterial);
    97.  
    98.       renderer.materials = materials.ToArray();
    99.     }
    100.   }
    101.  
    102.   void OnValidate() {
    103.  
    104.     needsUpdate = true;
    105.  
    106.     if (!precomputeOutline && bakeKeys.Count != 0 || bakeKeys.Count != bakeValues.Count) {
    107.       bakeKeys.Clear();
    108.       bakeValues.Clear();
    109.     }
    110.  
    111.     if (precomputeOutline && bakeKeys.Count == 0) {
    112.       Bake();
    113.     }
    114.   }
    115.  
    116.   void Update() {
    117.     if (needsUpdate) {
    118.       needsUpdate = false;
    119.  
    120.       UpdateMaterialProperties();
    121.     }
    122.   }
    123.  
    124.   void OnDisable() {
    125.     foreach (var renderer in renderers) {
    126.  
    127.       var materials = renderer.sharedMaterials.ToList();
    128.  
    129.       materials.Remove(outlineMaskMaterial);
    130.       materials.Remove(outlineFillMaterial);
    131.  
    132.       renderer.materials = materials.ToArray();
    133.     }
    134.   }
    135.  
    136.   void OnDestroy() {
    137.  
    138.     Destroy(outlineMaskMaterial);
    139.     Destroy(outlineFillMaterial);
    140.   }
    141.  
    142.   void Bake() {
    143.  
    144.     var bakedMeshes = new HashSet<Mesh>();
    145.  
    146.     foreach (var meshFilter in GetComponentsInChildren<MeshFilter>()) {
    147.  
    148.       if (!bakedMeshes.Add(meshFilter.sharedMesh)) {
    149.         continue;
    150.       }
    151.  
    152.       var smoothNormals = SmoothNormals(meshFilter.sharedMesh);
    153.  
    154.       bakeKeys.Add(meshFilter.sharedMesh);
    155.       bakeValues.Add(new ListVector3() { data = smoothNormals });
    156.     }
    157.   }
    158.  
    159.   void LoadSmoothNormals() {
    160.  
    161.     foreach (var meshFilter in GetComponentsInChildren<MeshFilter>()) {
    162.  
    163.       if (!registeredMeshes.Add(meshFilter.sharedMesh)) {
    164.         continue;
    165.       }
    166.  
    167.       var index = bakeKeys.IndexOf(meshFilter.sharedMesh);
    168.       var smoothNormals = (index >= 0) ? bakeValues[index].data : SmoothNormals(meshFilter.sharedMesh);
    169.  
    170.       meshFilter.sharedMesh.SetUVs(3, smoothNormals);
    171.  
    172.       var renderer = meshFilter.GetComponent<Renderer>();
    173.  
    174.       if (renderer != null) {
    175.         CombineSubmeshes(meshFilter.sharedMesh, renderer.sharedMaterials);
    176.       }
    177.     }
    178.  
    179.     foreach (var skinnedMeshRenderer in GetComponentsInChildren<SkinnedMeshRenderer>()) {
    180.  
    181.       if (!registeredMeshes.Add(skinnedMeshRenderer.sharedMesh)) {
    182.         continue;
    183.       }
    184.  
    185.       skinnedMeshRenderer.sharedMesh.uv4 = new Vector2[skinnedMeshRenderer.sharedMesh.vertexCount];
    186.  
    187.       CombineSubmeshes(skinnedMeshRenderer.sharedMesh, skinnedMeshRenderer.sharedMaterials);
    188.     }
    189.   }
    190.  
    191.   List<Vector3> SmoothNormals(Mesh mesh) {
    192.  
    193.     var groups = mesh.vertices.Select((vertex, index) => new KeyValuePair<Vector3, int>(vertex, index)).GroupBy(pair => pair.Key);
    194.  
    195.     var smoothNormals = new List<Vector3>(mesh.normals);
    196.  
    197.     foreach (var group in groups) {
    198.  
    199.       if (group.Count() == 1) {
    200.         continue;
    201.       }
    202.  
    203.       var smoothNormal = Vector3.zero;
    204.  
    205.       foreach (var pair in group) {
    206.         smoothNormal += smoothNormals[pair.Value];
    207.       }
    208.  
    209.       smoothNormal.Normalize();
    210.  
    211.       foreach (var pair in group) {
    212.         smoothNormals[pair.Value] = smoothNormal;
    213.       }
    214.     }
    215.  
    216.     return smoothNormals;
    217.   }
    218.  
    219.   void CombineSubmeshes(Mesh mesh, Material[] materials) {
    220.  
    221.     if (mesh.subMeshCount == 1) {
    222.       return;
    223.     }
    224.  
    225.     if (mesh.subMeshCount > materials.Length) {
    226.       return;
    227.     }
    228.  
    229.     mesh.subMeshCount++;
    230.     mesh.SetTriangles(mesh.triangles, mesh.subMeshCount - 1);
    231.   }
    232.  
    233.   void UpdateMaterialProperties() {
    234.  
    235.      outlineFillMaterial.SetColor("_OutlineColor", outlineColor);
    236.  
    237.     switch (outlineMode) {
    238.       case Mode.OutlineAll:
    239.         outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
    240.         outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
    241.         outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
    242.         break;
    243.  
    244.       case Mode.OutlineVisible:
    245.         outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
    246.         outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
    247.         outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
    248.         break;
    249.  
    250.       case Mode.OutlineHidden:
    251.         outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
    252.         outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
    253.         outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
    254.         break;
    255.  
    256.       case Mode.OutlineAndSilhouette:
    257.         outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
    258.         outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
    259.         outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
    260.         break;
    261.  
    262.       case Mode.SilhouetteOnly:
    263.         outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
    264.         outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
    265.         outlineFillMaterial.SetFloat("_OutlineWidth", 0f);
    266.         break;
    267.     }
    268.   }
    269. }
    270.