Created
November 3, 2015 11:25
-
-
Save Vengarioth/6be186a7d02448b47773 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Outline/OutlineBlendPass" { | |
Properties { | |
[HideInInspector] _MainTex ("Base (RGB)", 2D) = "white" {} | |
[HideInInspector] _OutlineBuffer ("Base (RGB)", 2D) = "white" {} | |
} | |
SubShader { | |
Pass | |
{ | |
Name "OutlineBlendPass" | |
Blend Off | |
AlphaTest Off | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#include "UnityCG.cginc" | |
sampler2D _MainTex; | |
sampler2D _OutlineBuffer; | |
float4 color0; | |
float4 color1; | |
float4 color2; | |
float4 color3; | |
struct v2f | |
{ | |
float4 pos : SV_POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
float4 _MainTex_ST; | |
v2f vert (appdata_base v) | |
{ | |
v2f o; | |
o.pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); | |
return o; | |
} | |
float4 frag (v2f i) : COLOR | |
{ | |
float4 background = tex2D(_MainTex, i.uv); | |
float4 factor = tex2D(_OutlineBuffer, i.uv); | |
float4 c; | |
if(factor.r > 0.1 && factor.r < 0.9) { | |
c = color0; | |
}else if(factor.g > 0.1 && factor.g < 0.9) { | |
c = color1; | |
}else if(factor.b > 0.1 && factor.b < 0.9) { | |
c = color2; | |
}else if(factor.a > 0.1 && factor.a < 0.9) { | |
c = color3; | |
}else{ | |
c = background; | |
} | |
return c; | |
} | |
ENDCG | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Outline/OutlineBlurPass" { | |
Properties { | |
[HideInInspector] _MainTex ("Base (RGB)", 2D) = "white" {} | |
} | |
SubShader { | |
Pass | |
{ | |
Name "HorizontalBlur" | |
Blend Off | |
AlphaTest Off | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#include "UnityCG.cginc" | |
sampler2D _MainTex; | |
struct v2f | |
{ | |
float4 pos : SV_POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
float4 _MainTex_ST; | |
v2f vert (appdata_base v) | |
{ | |
v2f o; | |
o.pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); | |
return o; | |
} | |
float4 frag (v2f i) : COLOR | |
{ | |
float blurAmount = 0.00035; | |
float4 fragment = tex2D(_MainTex, i.uv); | |
float4 sum = half4(0.0, 0.0, 0.0, 0.0); | |
sum += tex2D(_MainTex, float2(i.uv.x - 4.0 * blurAmount, i.uv.y)) * 0.05; | |
sum += tex2D(_MainTex, float2(i.uv.x - 3.0 * blurAmount, i.uv.y)) * 0.09; | |
sum += tex2D(_MainTex, float2(i.uv.x - 2.0 * blurAmount, i.uv.y)) * 0.12; | |
sum += tex2D(_MainTex, float2(i.uv.x - blurAmount, i.uv.y)) * 0.15; | |
sum += fragment * 0.16; | |
sum += tex2D(_MainTex, float2(i.uv.x + blurAmount, i.uv.y)) * 0.15; | |
sum += tex2D(_MainTex, float2(i.uv.x + 2.0 * blurAmount, i.uv.y)) * 0.12; | |
sum += tex2D(_MainTex, float2(i.uv.x + 3.0 * blurAmount, i.uv.y)) * 0.09; | |
sum += tex2D(_MainTex, float2(i.uv.x + 4.0 * blurAmount, i.uv.y)) * 0.05; | |
return sum; | |
} | |
ENDCG | |
} | |
Pass | |
{ | |
Name "VerticalBlur" | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#include "UnityCG.cginc" | |
sampler2D _MainTex; | |
struct v2f | |
{ | |
float4 pos : SV_POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
float4 _MainTex_ST; | |
v2f vert (appdata_base v) | |
{ | |
v2f o; | |
o.pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); | |
return o; | |
} | |
float4 frag (v2f i) : COLOR | |
{ | |
float blurAmount = 0.00035; | |
float4 fragment = tex2D(_MainTex, i.uv); | |
float4 sum = half4(0.0, 0.0, 0.0, 0.0); | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y - 4.0 * blurAmount)) * 0.05; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y - 3.0 * blurAmount)) * 0.09; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y - 2.0 * blurAmount)) * 0.12; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y - blurAmount)) * 0.15; | |
sum += fragment * 0.16; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y + blurAmount)) * 0.15; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y + 2.0 * blurAmount)) * 0.12; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y + 3.0 * blurAmount)) * 0.09; | |
sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y + 4.0 * blurAmount)) * 0.05; | |
return sum; | |
} | |
ENDCG | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public enum OutlineColor { | |
Color0, | |
Color1, | |
Color2, | |
Color3 | |
} | |
public class OutlineEffect : MonoBehaviour { | |
public GameObject TargetMesh; | |
public OutlineColor OutlineColor = OutlineColor.Color0; | |
public bool Active { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Outline/OutlineObjectPass" { | |
SubShader { | |
Pass { | |
Blend Off | |
Lighting Off | |
AlphaTest Off | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#pragma target 3.0 | |
#include "UnityCG.cginc" | |
sampler2D _CameraDepthNormalsTexture; | |
half4 weights; | |
struct vertOut { | |
float4 pos:SV_POSITION; | |
float4 screenPos:TEXCOORD1; | |
}; | |
vertOut vert(appdata_base v) : POSITION { | |
vertOut o; | |
o.pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
o.screenPos = ComputeScreenPos(o.pos); | |
return o; | |
} | |
half4 frag(vertOut i) : COLOR { | |
i.screenPos.xyz /= i.screenPos.w; | |
#ifdef SHADER_API_D3D11 | |
float fragDepth = i.screenPos.z; | |
#else | |
float fragDepth = (i.screenPos.z + 1) / 2; | |
#endif | |
float3 normalValues; | |
float depthValue; | |
float4 x = tex2D(_CameraDepthNormalsTexture, i.screenPos.xy); | |
DecodeDepthNormal(x, depthValue, normalValues); | |
if(depthValue < (Linear01Depth(fragDepth) - 0.0005)) | |
{ | |
return half4(0.0, 0.0, 0.0, 0.0); | |
} | |
return weights; | |
} | |
ENDCG | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
public class OutlineRenderer : LocatableByType<OutlineRenderer> | |
{ | |
public Shader outlineObjectShader; | |
public Shader outlineBlurShader; | |
public Shader outlineBlendShader; | |
private Material outlineObjectMaterial; | |
private Material outlineBlurMaterial; | |
private Material outlineBlendMaterial; | |
public Color color0; | |
public Color color1; | |
public Color color2; | |
public Color color3; | |
private RenderTexture outlineBuffer; | |
private RenderTexture outlineBuffer2; | |
// Use this for initialization | |
void Start () { | |
outlineObjectMaterial = new Material(outlineObjectShader); | |
outlineBlurMaterial = new Material(outlineBlurShader); | |
outlineBlendMaterial = new Material(outlineBlendShader); | |
var camera = Camera.main; | |
camera.depthTextureMode = DepthTextureMode.DepthNormals; | |
outlineBuffer = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 16); | |
outlineBuffer.Create(); | |
outlineBuffer2 = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 16); | |
outlineBuffer2.Create(); | |
} | |
void OnRenderImage (RenderTexture src, RenderTexture dest) { | |
var outlineEffects = GameObject.FindObjectsOfType<OutlineEffect>(); | |
var lastActiveRenderTexture = RenderTexture.active; | |
var camera = Camera.main; | |
if(camera.pixelWidth != outlineBuffer.width || camera.pixelHeight != outlineBuffer.height) | |
{ | |
outlineBuffer.Release(); | |
outlineBuffer.width = camera.pixelWidth; | |
outlineBuffer.height = camera.pixelHeight; | |
outlineBuffer.Create(); | |
outlineBuffer2.Release(); | |
outlineBuffer2.width = camera.pixelWidth; | |
outlineBuffer2.height = camera.pixelHeight; | |
outlineBuffer2.Create(); | |
} | |
RenderTexture.active = outlineBuffer2; | |
GL.Clear(true, true, new Color(0f, 0f, 0f, 0f)); | |
RenderTexture.active = outlineBuffer; | |
GL.Clear(true, true, new Color(0f, 0f, 0f, 0f)); | |
foreach(var outlineEffect in outlineEffects) | |
{ | |
if (!outlineEffect.Active) | |
continue; | |
switch(outlineEffect.OutlineColor) | |
{ | |
case OutlineColor.Color0: | |
outlineObjectMaterial.SetVector("weights", new Vector4(1.0f, 0f, 0f, 0f)); | |
break; | |
case OutlineColor.Color1: | |
outlineObjectMaterial.SetVector("weights", new Vector4(0f, 1.0f, 0f, 0f)); | |
break; | |
case OutlineColor.Color2: | |
outlineObjectMaterial.SetVector("weights", new Vector4(0f, 0f, 1.0f, 0f)); | |
break; | |
case OutlineColor.Color3: | |
outlineObjectMaterial.SetVector("weights", new Vector4(0f, 0f, 0f, 1.0f)); | |
break; | |
} | |
//needs to be set after all material properties have been set | |
while(!outlineObjectMaterial.SetPass(0)) { Debug.Log("Could not render with material, repeating..."); } | |
var go = outlineEffect.TargetMesh; | |
var m = go.transform.localToWorldMatrix; | |
var meshFilter = go.GetComponent<MeshFilter>(); | |
if(meshFilter != null) { | |
Graphics.DrawMeshNow(meshFilter.sharedMesh, m); | |
}else{ | |
var skinnedMeshRenderer = go.GetComponentInChildren<SkinnedMeshRenderer>(); | |
if(skinnedMeshRenderer != null) | |
{ | |
var mesh = new Mesh(); | |
skinnedMeshRenderer.BakeMesh(mesh); | |
Graphics.DrawMeshNow(mesh, m); | |
} | |
} | |
} | |
Graphics.Blit(outlineBuffer, outlineBuffer2, outlineBlurMaterial, 0); | |
Graphics.Blit(outlineBuffer2, outlineBuffer, outlineBlurMaterial, 1); | |
outlineBlendMaterial.SetTexture("_OutlineBuffer", outlineBuffer); | |
outlineBlendMaterial.SetColor("color0", color0); | |
outlineBlendMaterial.SetColor("color1", color1); | |
outlineBlendMaterial.SetColor("color2", color2); | |
outlineBlendMaterial.SetColor("color3", color3); | |
RenderTexture.active = lastActiveRenderTexture; | |
Graphics.Blit(src, dest, outlineBlendMaterial); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Deferred outlines for Unity3d (Unoptimized, proof of concept) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment