Skip to content

Instantly share code, notes, and snippets.

@Vavassor
Created November 19, 2025 20:13
Show Gist options
  • Select an option

  • Save Vavassor/a8d8c047288b76f3a61e0987e330b762 to your computer and use it in GitHub Desktop.

Select an option

Save Vavassor/a8d8c047288b76f3a61e0987e330b762 to your computer and use it in GitHub Desktop.
Wire Shader for Unity's built in render pipeline. Based on Phone-wire AA by Humus
// Wire shader that prevents prevent thin wires from becoming disconnected pixels at a distance.
//
// The wire drawing method is based on "Phone-wire AA" by Emil Persson aka Humus.
// https://www.humus.name/index.php?page=3D&ID=89
//
// MIT License
// Copyright © 2025 Andrew Dawson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Shader "Orchid Seal/Wire/Wire Surface"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
[Header(Wire)]
_WireRadius ("Wire Radius", float) = 0.01
_WireSharpness ("Wire Sharpness", Range(0.3, 1)) = 0.8
[Toggle] _WireAdjustUv("Adjust UVs when Far", Integer) = 1
[Toggle] _WireVertexColorNormalsOn("Vertex Color Normals - Poiyomi's Outline Vertex Color tool can add these.", Integer) = 0
[Header(Masks)]
[Toggle(_METALLICGLOSSMAP)] _MaskMapOn("Enabled", Integer) = 0
[Gamma] _Metallic ("Metallic", Range(0,1)) = 0.0
_Glossiness ("Smoothness", Range(0,1)) = 0.5
[NoScaleOffset] _MaskMap("Mask - Metallic (R) and Smoothness (A)", 2D) = "black" {}
[Header(Normal)]
[Toggle(_NORMALMAP)] _NormalMapOn("Enabled", Integer) = 0
_BumpScale ("Normal Scale", Range(0, 5)) = 1
[Normal] [NoScaleOffset] _BumpMap ("Normal", 2D) = "bump" {}
[Header(Reflection)]
[ToggleOff(_SPECULARHIGHLIGHTS_OFF)]_SpecularHighlights ("Specular Highlights", Float) = 1.0
[ToggleOff(_GLOSSYREFLECTIONS_OFF)]_GlossyReflections ("Glossy Reflections", Float) = 1.0
[Header(Culling and Depth Test)]
[Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull Mode", Int) = 2 // "Back"
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 //"LessEqual"
[Enum(Off,0,On,1)] _ZWrite("ZWrite", Float) = 1.0 //"On"
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
Cull [_Cull]
ZTest [_ZTest]
ZWrite [_ZWrite]
CGPROGRAM
#pragma surface surf Standard fullforwardshadows addshadow alpha:fade vertex:disp exclude_path:deferred
#pragma target 3.0
#pragma shader_feature_local _METALLICGLOSSMAP
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature_local _GLOSSYREFLECTIONS_OFF
struct VertexInput
{
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
float2 texcoord1 : TEXCOORD1;
float2 texcoord2 : TEXCOORD2;
};
struct Input
{
float2 uv_MainTex;
centroid float fade;
};
sampler2D _MainTex;
sampler2D _MaskMap;
sampler2D _BumpMap;
half _Glossiness;
half _Metallic;
half _BumpScale;
fixed4 _Color;
half _WireRadius;
half _WireSharpness;
half _WireAdjustUv;
half _WireVertexColorNormalsOn;
void disp(inout VertexInput v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
float3 wireNormal = v.normal;
if (_WireVertexColorNormalsOn)
{
float3 normal = v.normal.xyz;
float3 tangent = v.tangent.xyz;
float3 bitangent = normalize(cross(normal, tangent)) * (v.tangent.w * length(normal));
float3 normalTs = v.color.rgb * 2.0 - 1.0;
wireNormal = normalTs.x * tangent + normalTs.y * bitangent + normalTs.z * normal;
}
float radiusMax = max(_WireRadius, 0.001);
float3 deflatedPosition = v.vertex.xyz - radiusMax * wireNormal;
float w = dot(UNITY_MATRIX_MVP[3], float4(deflatedPosition, 1.0f));
// TODO: _WireSharpness should be unnecessary but for some reason it looks bad at 1? -Vavassor
float pixelRadius = w / (_WireSharpness * unity_CameraProjection._m11 * _ScreenParams.y);
float radius = max(radiusMax, pixelRadius);
v.vertex.xyz = v.vertex.xyz + (radius - radiusMax) * wireNormal;
if (_WireAdjustUv)
{
float2 uv = v.texcoord;
uv.x *= 0.02 / radius;
v.texcoord.xy = uv;
}
o.fade = _WireRadius / radius;
}
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a * IN.fade;
#if _METALLICGLOSSMAP
half4 masks = tex2D(_MaskMap, IN.uv_MainTex);
o.Metallic = _Metallic * masks.r;
o.Smoothness = _Glossiness * masks.a;
#else
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
#endif
#if _NORMALMAP
o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
#endif
}
ENDCG
}
Fallback "Standard"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment