Skip to content

Instantly share code, notes, and snippets.

@unitycoder
Created September 30, 2025 11:45
Show Gist options
  • Save unitycoder/a93c4d64b9e639246ba0fbe0c2875f5c to your computer and use it in GitHub Desktop.
Save unitycoder/a93c4d64b9e639246ba0fbe0c2875f5c to your computer and use it in GitHub Desktop.

Revisions

  1. unitycoder created this gist Sep 30, 2025.
    89 changes: 89 additions & 0 deletions OutlineOnlyHDR.shader
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,89 @@
    // by Mr. Chap Gipity
    Shader "Custom/OutlineOnlyHDR"
    {
    Properties
    {
    [HDR]_OutlineColor("Outline (HDR Emission)", Color) = (5,5,5,1)
    _OutlineWidth("Width (view-space units)", Float) = 0.02
    _ZOffset("Depth Offset (units)", Float) = 0.0
    }
    SubShader
    {
    Tags { "RenderType"="Opaque" "Queue"="Geometry+1" }

    // We only want the silhouette halo, so we draw
    // inflated backfaces after regular geometry.
    Pass
    {
    Name "OUTLINE_ONLY"
    Tags { "LightMode"="Always" }

    Cull Front // draw backfaces only (silhouette)
    ZWrite On
    ZTest LEqual
    Offset 0, 0 // polygon offset off by default; use _ZOffset below

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma target 3.0
    #pragma multi_compile_instancing

    #include "UnityCG.cginc"

    fixed4 _OutlineColor;
    float _OutlineWidth;
    float _ZOffset;

    struct appdata
    {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    UNITY_VERTEX_INPUT_INSTANCE_ID
    };

    struct v2f
    {
    float4 pos : SV_POSITION;
    UNITY_VERTEX_INPUT_INSTANCE_ID
    UNITY_VERTEX_OUTPUT_STEREO
    };

    v2f vert (appdata v)
    {
    v2f o;
    UNITY_SETUP_INSTANCE_ID(v);
    UNITY_INITIALIZE_OUTPUT(v2f, o);
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

    // World space position & normal
    float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    float3 worldNrm = UnityObjectToWorldNormal(v.normal);

    // View space position & normal
    float3 viewPos = mul(UNITY_MATRIX_V, float4(worldPos, 1)).xyz;
    float3 viewNrm = normalize(mul((float3x3)UNITY_MATRIX_V, worldNrm));

    // Extrude along view-space normal for (almost) constant on-screen thickness
    viewPos += viewNrm * _OutlineWidth;

    // Optional depth nudge to avoid z-fighting at grazing angles
    viewPos.z += _ZOffset;

    // Project
    o.pos = mul(UNITY_MATRIX_P, float4(viewPos, 1));

    return o;
    }

    fixed4 frag (v2f i) : SV_Target
    {
    // Unlit, pure emission. Use HDR color for bloom.
    return _OutlineColor;
    }
    ENDCG
    }
    }

    Fallback Off
    }