- Home /
Is there a shader to only add an outline?
The toon shaders have outlines, but also change the shading of the object. I'd like to show an outline without affecting the rest of the shading. Also if possible, only show outline around the perimeter of the object and not on edges in the middle.
I have no idea how to program shaders, so if anyone knows how to do this or can point me in the direction of a shader that already exists, I would appreciate it greatly. Thanks!
Do you want just an outline or an outline with a shading model inside such as a outline diffuse
Peter, I'm not sure what you mean by those options in comparison to each other. I just want a model to look normal (such as the standard diffuse or diffuse bump shader, except with an outline around the whole thing. You see this kind of effect in a lot of games, such as when the mouse is pointing at the object being outlined.
Answer by xortrox · Aug 21, 2014 at 08:21 PM
Bumping an extremely old post here, but considering the fact that I came by it when trying to figure this out myself here's for the others that might end up here:
(from the bottom of: http://wiki.unity3d.com/index.php/Silhouette-Outlined_Diffuse)
This will give you an outline only, based on an input color. All you gotta do is add it as a separate material to your target object.
Answer by Draco18s · Sep 12, 2015 at 09:07 PM
Old post, but also highest ranked on google for this topic. I just spent several hours writing a geometry shader that's much improved compared to a toon or silhouette shader by taking every edge in the mesh and turning those edges into quads rendered facing the camera. This means that it works on cubes in a satisfying manner. Be aware that this is not a mobile-friendly shader, due to using the stencil buffer and rendering the object twice, and requires forward lighting. It also does not render the object itself, just the outline (due to my own needs) but should be easily modifiable to render the original mesh as well.
Note that because verts are supplied going clockwise around the surface normal, single sided quads will only render 3 edges (the other two are facing away from the camera). Similarly, at hard corners, the corners will be noticeably thinner than other areas, but this is only a problem at very high thickness values (greater than 10, which is pretty darn thick). This has to do with the quad's corners not being fused with the neighboring triangle's quads.
Both of these problems are technically solvable, but wasn't worth the effort for my use, due to only being apparent in edge-cases I wasn't going to be using. The former can be solved by rendering the front and back face of each quad (and correspondingly increasing maxvertexcount
by double). The latter might be solved by using triangleadj
in the geometry shader portion, instead of triangle
, and calculating intersection points. See: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509609%28v=vs.85%29.aspx
If there's an issue with it rendering strangely, swap float4 parallel = end.pos-start.pos;
for float4 parallel = start.pos-end.pos;
which I had to do when I merged this shader into another for use as a replacement shader that handles particular special rendering effects. Why? No idea.
Shader "Stencil/Outline"
{
Properties
{
_Color("Color", Color) = (1,0,0,1)
_Thickness("Thickness", float) = 4
}
SubShader
{
Tags { "Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZTest always
Pass
{
Stencil {
Ref 1
Comp always
Pass replace
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2g
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
struct g2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
v2g vert(appdata_base v)
{
v2g OUT;
OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
OUT.uv = v.texcoord;
OUT.normals = v.normal;
OUT.viewT = ObjSpaceViewDir(v.vertex);
return OUT;
}
half4 frag(g2f IN) : COLOR
{
//this renders nothing, if you want the base mesh and color
//fill this in with a standard fragment shader calculation
return 0;
}
ENDCG
}
Pass
{
Stencil {
Ref 0
Comp equal
}
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 4.0
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
half4 _Color;
float _Thickness;
struct v2g
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
struct g2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
v2g vert(appdata_base v)
{
v2g OUT;
OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
OUT.uv = v.texcoord;
OUT.normals = v.normal;
OUT.viewT = ObjSpaceViewDir(v.vertex);
return OUT;
}
void geom2(v2g start, v2g end, inout TriangleStream<g2f> triStream)
{
float thisWidth = _Thickness/100;
float4 parallel = end.pos-start.pos;
normalize(parallel);
parallel *= thisWidth;
float4 perpendicular = float4(parallel.y,-parallel.x, 0, 0);
perpendicular = normalize(perpendicular) * thisWidth;
float4 v1 = start.pos-parallel;
float4 v2 = end.pos+parallel;
g2f OUT;
OUT.pos = v1-perpendicular;
OUT.uv = start.uv;
OUT.viewT = start.viewT;
OUT.normals = start.normals;
triStream.Append(OUT);
OUT.pos = v1+perpendicular;
triStream.Append(OUT);
OUT.pos = v2-perpendicular;
OUT.uv = end.uv;
OUT.viewT = end.viewT;
OUT.normals = end.normals;
triStream.Append(OUT);
OUT.pos = v2+perpendicular;
OUT.uv = end.uv;
OUT.viewT = end.viewT;
OUT.normals = end.normals;
triStream.Append(OUT);
}
[maxvertexcount(12)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream)
{
geom2(IN[0],IN[1],triStream);
geom2(IN[1],IN[2],triStream);
geom2(IN[2],IN[0],triStream);
}
half4 frag(g2f IN) : COLOR
{
_Color.a = 1;
return _Color;
}
ENDCG
}
}
FallBack "Diffuse"
}
looks pretty well but why is the outline only visible in the scene view?
@leonalchemist I'm not sure. Are you using deferred rendering? The stencil buffer is used for deferred rendering and the shader would conflict with that. You have to use forward rendering.
i see, thx for the info; not sure it's something I want to do though and it does look pretty weird in the game view
It isn't meant to have high thickness values, as the edges of the interpolated quads don't line up. This is the intended thickness: http://s21.postimg.org/lrzm1h21j/finally.png And here's massively overdoing it: http://s17.postimg.org/rwdam5g2n/blow_out.png I forget what values I used for each of those, I think the first is around 20.
@Draco18s this shader is great. Seems to be the best solution I've found so far, but unfortunately in Unity 5.4 beta, it doesn't render correctly in Game view. As @leonalchemist found, Legacy Deferred is the only render mode that works. Do you have any ideas about how to get it working again in Forward mode?
Offhand, no. I would need to play with it and even then no guarantees. I had to BS my way through the code the first time through, trying things and hoping it worked.
Funny, also couldn't reply to your last post.
Unity is absolutely doing something during deferred rendering: lights.
Yeah the strange thing is it also seems to be doing something in forward rendering mode. Not 100% sure, just basing this suspicion on the fact that it won't work in forward mode, but will work in deferred mode standard shader without the deferred pass.
Really weird. I only know about the stencil bits in deferred, because it's on the manual page for stencil shaders.
Took me a couple of days to write it, having to learn several things about HLSL. Hope you make good use of it, as far as I know it's the only freely available outline shader out there that isn't a simple scalar (which is precisely why I wrote it).
Yea, I tried to learn more about shaders but it was such a painful and miserable experience. If you have any resource that you could share or book that you used to learn from please let me know ;-)
Thanks for your work man!
Thank you for sharing this, new to shaders. is exactly what i was looking for and is very beautiful ;) cheers sir
Just wanted to say this works great for adding just an outline if you just add a new material. Worked perfectly on Unity 2017.2.0f3. Thanks for posting this!
Also would you $$anonymous$$d if this was posted on the wiki page with the other shaders?
Answer by Muzz 1 · Apr 23, 2011 at 05:10 PM
Find and download the Strumpy Shader Editor in the Asset Store (it's free!) and you can probably get exactly what you want to.
Answer by Teare · Apr 23, 2011 at 05:11 PM
http://wiki.unity3d.com/index.php/Shader_Archive
Try looking through these.
Answer by Cherno · Aug 21, 2014 at 09:15 PM
I recommend this post by Boolean:
http://forum.unity3d.com/threads/trying-to-make-a-silhouette-outline-shader.96005/#post-1408098
In my opinion, it's better than the Silhouette Ouline Diffuse shader from the wiki, it hasn't got the same overlap issues and the effect is also very cool.
Also take a look at my own modifications to this shader as detailed here:
http://answers.unity3d.com/questions/667483/silhouette-outline-shader-problem-with-overlapping.html
Your answer
Follow this Question
Related Questions
QuickOutline: how can I change the shader to work with objects with two materials? 3 Answers
Shader Edit Help: 2D Outline Coloring 2 Answers
Blueprint Shader 2 Answers
Object outline component 0 Answers
Outline Shader HELP 0 Answers