Repository: Shrimpey/Outlined-Diffuse-Shader-Fixed Branch: master Commit: f7179d1bbb51 Files: 9 Total size: 15.8 KB Directory structure: gitextract_6ztqttvw/ ├── CustomOutline-CameraIndependent.shader ├── CustomOutline-ConstantWidth.shader ├── CustomOutline.shader ├── LICENSE ├── OutlineShowcase.unitypackage ├── README.md ├── RegularOutline.shader ├── UniformOutline.shader └── triangleOutline.shader ================================================ FILE CONTENTS ================================================ ================================================ FILE: CustomOutline-CameraIndependent.shader ================================================ // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Outlined/Custom Camera Independent" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline2 ("Outline width", Range (0, 1)) = .1 _MainTex ("Base (RGB)", 2D) = "white" { } } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; float4 color : COLOR; }; uniform float _Outline2; uniform float4 _OutlineColor; v2f vert(appdata v) { // just make a copy of incoming vertex data but scaled according to normal direction v2f o; //Camera position in world float3 targetPos = _WorldSpaceCameraPos; //Object position in world float3 objectPos = mul (unity_ObjectToWorld, v.vertex).xyz; //Vertex offset from center of the object float3 offset = v.vertex.xyz; //Distance from the object to the camera float dist = distance(objectPos, targetPos + offset); //Forward vector of the camera float3 viewDir = UNITY_MATRIX_IT_MV[2].xyz; //Vector between vertex and offseted camera pos float3 distVec = objectPos - (targetPos + offset); //Angle between two vectors float angle = distVec - distVec; //float angle = atan2(normalize(cross(distVec,viewDir)), dot(distVec,viewDir)); //Real distance (to the plane 90 degrees to camera forward and object) float finalDist = dist * cos(degrees(angle)); //v.vertex *= ( 2 ); v.vertex *= finalDist * _Outline2; //v.vertex *= -1; o.pos = UnityObjectToClipPos(v.vertex); o.color = _OutlineColor; return o; } ENDCG SubShader { //Tags {"Queue" = "Geometry+100" } CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG // note that a vertex shader is specified here but its using the one above Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha //Offset 50,50 CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) :COLOR { return i.color; } ENDCG } } SubShader { CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma exclude_renderers gles xbox360 ps3 ENDCG SetTexture [_MainTex] { combine primary } } } Fallback "Diffuse" } ================================================ FILE: CustomOutline-ConstantWidth.shader ================================================ // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Outlined/Custom Constant Width" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (0, 5)) = .1 _Limiter ("Outline width limiter", Range (0, 5)) = 0 _MainTex ("Base (RGB)", 2D) = "white" { } } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; float4 color : COLOR; }; uniform float _Outline; uniform float _Limiter; uniform float4 _OutlineColor; v2f vert(appdata v) { v2f o; //Original concept of using FOV //float t = unity_CameraProjection._m11; //const float Rad2Deg = 180 / UNITY_PI; //float fov = atan(1.0f / t ) * 2.0 * Rad2Deg; //if(fov < _Limiter){ // fov = _Limiter; //} float multiplier = unity_OrthoParams.x * 0.1; if(multiplier < _Limiter){ multiplier = _Limiter; } v.vertex *= _Outline * multiplier; o.pos = UnityObjectToClipPos(v.vertex); o.color = _OutlineColor; return o; } ENDCG SubShader { //Tags {"Queue" = "Geometry+100" } CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG // note that a vertex shader is specified here but its using the one above Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha //Offset 50,50 CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) :COLOR { return i.color; } ENDCG } } SubShader { CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma exclude_renderers gles xbox360 ps3 ENDCG SetTexture [_MainTex] { combine primary } } } Fallback "Diffuse" } ================================================ FILE: CustomOutline.shader ================================================ // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Outlined/Custom" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (0, 1)) = .1 _MainTex ("Base (RGB)", 2D) = "white" { } } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; float4 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; v.vertex *= ( 1 + _Outline); o.pos = UnityObjectToClipPos(v.vertex); //float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal)); //float2 offset = TransformViewToProjection(norm.xy); o.color = _OutlineColor; return o; } ENDCG SubShader { //Tags {"Queue" = "Geometry+100" } CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG // note that a vertex shader is specified here but its using the one above Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha //Offset 50,50 CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) :COLOR { return i.color; } ENDCG } } SubShader { CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma exclude_renderers gles xbox360 ps3 ENDCG SetTexture [_MainTex] { combine primary } } } Fallback "Diffuse" } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2017 Luke Kabat 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. ================================================ FILE: README.md ================================================ # Outlined Diffuse Shader Fixed for Unity 5.6 This is a fixed version of diffused outline shader from http://wiki.unity3d.com/index.php/Outlined_Diffuse_3 It should be working fine in Unity 5.6 and above. # Important update: **A new version of the outline shader is available, go to: https://github.com/Shrimpey/UltimateOutline Use the updated shader, come back here only if you find it to be working weirdly on your custom models and try some of the ones mentioned below.** **Guide:** I suggest you trying **UniformOutline.shader** and then **CustomOutline.shader**. They should work fine for simple objects/complex objects with proper origin. If they fail - try out the **RegularOutline.shader**. The rest of the shaders are for really specyfic purposes, so unless you know what you're doing you probably shouldn't be using them :) **Showcase:** Download **OutlineShowcase.unitypackage** and import it to Unity project to see RegularOutline, CustomOutline and UniformOutline shaders in action. **Shaders:** # RegularOutline.shader **RegularOutline.shader** - Just an updated version of the shader from the wiki page, may still work in weird ways => if so, use custom one. ![Regular Outline](/images/standard.PNG?raw=true "Regular Outline") **Usage**: Curved shapes/thin outlines. **Problems**: Weird shapes on hard edges. --- # CustomOutline.shader **CustomOutline.shader** - My personal take on the outline shader. It increases the scale of the vertices instead of working with normals. ![Custom Outline](/images/custom.PNG?raw=true "Custom Outline") **Usage**: All shapes **Problems**: Possible clipping on really thick edges/weird offsets if model's origin is not in center --- # UniformOutline.shader **UniformOutline.shader** - Made from scratch, works just like CustomOutline except the scaling is more uniform - width of the outline should be more consistent on irregular meshes (easy to notice when comparing the wheels of the cart from the image below to the Custom Outline shader image). ![Uniform Outline](/images/Uniform.PNG?raw=true "Uniform Outline") **Usage**: All shapes **Problems**: Same as in Custom Outline, less overlaying, more angled distortions. --- # CustomOutline-CameraIndependent.shader **CustomOutline-CameraIndependent.shader** - Same as custom one, but the outline is the same width despite the distance to the camera. ![Camera Independend Close](/images/camera.PNG?raw=true "Camera Independend Close") ![Camera Independend Far](/images/camera2.PNG?raw=true "Camera Independend Far") **Usage**: Same sized outline on perspective camera. **Problems**: Weird shapes on complex objects. --- # CustomOutline-ConstantWidth.shader **CustomOutline-ConstantWidth.shader** - Same as custom one, but the outline is constant width despite the camera zoom. ![Constant Width Zoomed In](/images/zoom2.PNG?raw=true "Constant Width Zoomed In") ![Constant Width Zoomed Out](/images/zoom.PNG?raw=true "Constant Width Zoomed Out") **Usage**: Same outline width despite the camera's zoom (ortho/perspective) **Problems**: Clipping on thick outlines on complex shapes. --- *UPDATE 03.09.2017 - Added camera independent version of custom shader* *UPDATE 04.09.2017 - Added constant size version of custom shader | updated README to include images* *UPDATE 12.09.2017 - Added uniform outline shader* *UPDATE 23.12.2017 - Fixed some minor issues with custom, regular and uniform shaders | added showcase unity package* ================================================ FILE: RegularOutline.shader ================================================ Shader "Outlined/Regular" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (0, 1)) = .1 _MainTex ("Base (RGB)", 2D) = "white" { } } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; float4 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 = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal); float2 offset = TransformViewToProjection(norm.xy); o.pos.xy += offset * o.pos.z * _Outline; o.color = _OutlineColor; return o; } ENDCG SubShader { Tags { "Queue" = "Transparent" "IgnoreProjector" = "True"} Cull Back CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG Pass { Name "OUTLINE" Tags { "Queue" = "Transparent" "IgnoreProjector" = "True"} Cull Front ZWrite Off //ZTest Less //Offset 1, 1 CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) :COLOR { return i.color; } ENDCG } } Fallback "Diffuse" } ================================================ FILE: UniformOutline.shader ================================================ Shader "Outlined/Uniform" { Properties { _Color("Main Color", Color) = (0.5,0.5,0.5,1) _MainTex ("Texture", 2D) = "white" {} _OutlineColor ("Outline color", Color) = (0,0,0,1) _OutlineWidth ("Outlines width", Range (0.0, 2.0)) = 1.1 } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 pos : POSITION; }; uniform float _OutlineWidth; uniform float4 _OutlineColor; uniform sampler2D _MainTex; uniform float4 _Color; ENDCG SubShader { Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" } Pass //Outline { ZWrite Off Cull Back CGPROGRAM #pragma vertex vert #pragma fragment frag v2f vert(appdata v) { appdata original = v; v.vertex.xyz += _OutlineWidth * normalize(v.vertex.xyz); v2f o; o.pos = UnityObjectToClipPos(v.vertex); return o; } half4 frag(v2f i) : COLOR { return _OutlineColor; } ENDCG } Tags{ "Queue" = "Geometry"} CGPROGRAM #pragma surface surf Lambert struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } Fallback "Diffuse" } ================================================ FILE: triangleOutline.shader ================================================ Shader "Outlined/Triangle" { Properties { _Color("Main Color", Color) = (0.5,0.5,0.5,1) _MainTex ("Texture", 2D) = "white" {} _OutlineColor ("Outline color", Color) = (0,0,0,1) _OutlineWidth ("Outlines width", Range (0.0, 2.0)) = 1.1 } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 pos : POSITION; }; uniform float _OutlineWidth; uniform float4 _OutlineColor; uniform sampler2D _MainTex; uniform float4 _Color; ENDCG SubShader { Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" } Pass //Outline { ZWrite Off Cull Back CGPROGRAM #pragma vertex vert #pragma fragment frag v2f vert(appdata v) { appdata original = v; v.vertex.xyzw += _OutlineWidth * normalize(v.vertex.xyzw); v.vertex.x -= _OutlineWidth/4; v.vertex.y += _OutlineWidth/4; v2f o; o.pos = UnityObjectToClipPos(v.vertex); return o; } half4 frag(v2f i) : COLOR { return _OutlineColor; } ENDCG } Tags{ "Queue" = "Geometry"} CGPROGRAM #pragma surface surf Lambert struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } Fallback "Diffuse" }