Excellent! I will try to apply this with different kernels / operators than Sobel. One slightly annoying thing is that the outline is amplified where objects are overlapping (one behind the other) in the view. The effect is even more prominent when the outlines are different colors, essentially picking "false" edges for occluded objects. This is most likely a byproduct of the edge detection + Screen Position, since there is a much clearer difference in intensity at the overlapping points. Couple that with different outline colors and the effect goes wild. This seems like a hard problem to tackle. An ideal theoretical solution would be to draw the objects one by one, starting from the farthest and performing edge detection on a single object a time, then overlapping the results. This seems like a pain in the ass and the most un-optimized solution ever (at least for Unity, things may be different if one codes it from scratch). I'm actually not noticing the effect on your previous videos that aren't object-based - Granted, it is harder to notice since the outline is one color.
Hi! Yeah, this is difficult to solve. It's due to the outline only rendering on top of it's mesh, so the part of the outline that resides outside the object isn't rendered. This isn't a problem when the algorithm is run over the entire screen, since the shader can happily draw wherever it wants to.
@@NedMakesGames Hello, thanks for the reply! I'm going to try render Layers and (probably) replacement shaders to emulate per object outline. It might be doable. Also, why is it that a render feature running only once is heavier than running the edge detection per object? Is adding a render feature as post processing that much heavier than running the detection multiple times?
@@CSPlayerDamon No problem! I hope your project goes smoothly! Post processing is really only an issue on mobile platforms. Memory access can be slow and post process effects require that you copy the screen texture back and forth in a buffer. Then, of course, post processing runs over the entire screen, instead of just the meshes to be outlined. This can be a big problem when the GPU is already busy. It's even worse in VR, since post processing has to run once for each eye.
Amazing tutorials as always Ned! Love your work, one of the absolute best. I was curious if you think you'd be able to cover water one day. Specifically how game devs handle above water and separate under water rendering, as well as the meniscus. That was always something I wanted to learn about.
Thank you so much! Glad you enjoyed it! I’m definitely planning multiple series on different aspects of water rendering. I’ll keep your request in mind!
I don't understand the value of the matrix at 3:00. If you are using the Sobel operator, the matrix should be: 1, 0, -1 2, 0, -2 1, 0, -1 for horizontal edge detection, as shown in your code at 3:17. What am i missing?
A problem with this is that the outer outline only eats into the object when it should also expand out of the object. This makes the outer outlines thinner and makes weird artifacts when objects overlap. I couldn't think of a way to solve this. So maybe backface culling is the way to go for per object outlining.
@@ThomasChen-ur2gt Yeah, this is a disadvantage of this system, and it's tough to avoid. You would have to calculate if an outline is in the interior of an object and then use a different thickness. You could probably do this by calculating depth sobel once with high thickness, using that to adjust the outline thickness value, and calculating depth and normal sobel again for the actual outline. But that wouldn't catch objects overlapping. Hmm... It would be interesting to try hull and edge detection together!
@@NedMakesGames Conceptually what they did is that they only use the interior edge texels for the sobel filter, which makes the silhouette lines behave like inner lines!
Working in 2021.3. After changing *_float to *_half, changing precision to Half, I got rid of identifiers errors. Maked sure the Blend-node was set to Overwrite, but still no outlines, just the plain Base color. Am I missing something?
Those are the two most common errors. You can try routing individual parts to base color to see if they make sense. I can also take a look at your graph if you'd like to post a screenshot. (I would recommend emailing me or posting to Discord, since TH-cam tends to hide comments with links.)
@@NedMakesGames Thank you for willing to look into this. But while making screenshots for you, I noticed 2 mistakes on my side, one in the SobelFineTuning and one in the Outlines. After fixing them, the outlines appeared! Looks like it's working as hoped although further tweaking may take some time. Thanks for your great tutorials and service on this!
@@dontassumably3603 I fixed it by realy, realy carefully checking every node. It were just 2 sloppy mistakes. I think it was a wrongly connected node at SobelFineTuning and I forget to set a value somewhere. Pretty noobs mistakes... But just staying patient while checking nodes did the trick eventually
Still trying to make this shader work for my VR project. Shader looks fine (real fine!) in Unity, but on the Quest 2 it gets 'glitchy'. I hope to fix that/make it acceptable with different settings of the parameters. The main problem now is when I try to bake the static objects in my scene, the objects with the ToonOutlineShader turn completly black. A few static objects with URP Simple Lit Shaders behave like expected, the ToonOutlineShaded objects aren't. Is this shader just not suitable for being baked Lightmaps or am I missing something?
Hmm, which version of Unity are you using? I have not seen that, but Shader Graphs can act strangely with baked lighting. This effect is just difficult to get working on the Quest. It's very expensive to use full screen textures, like the depth-normals texture. The glitchyness could be from low frame rate. Do you see that in a super simple scene? Sometimes float precision can be an issue. You can try lowering the camera's far clip plane to improve that.
Works. Unfortunately, in my terrain (procedurally generated) it shows some artifacts, random dots here and there detected as edges. I am guessing it happens where 2 terrain chunks meet. Looks like unity has random 1-pixel holes in the depth texture.
Hi, i have problem when i'm trying to combine it with dissolve shader. I'm using alpha clip to dissolve mesh and it works fine with outline until there is other object with outline behind it. The part of outline that should be invisible is now visible on the mesh behind it.
Hi! Outlines in general are tricky to get working with transparency. I think Unity's "Hidden/Internal-DepthNormalsTexture" shader doesn't take alpha clipping into account, which can produce these kinds of results. You could write a custom depth-normals-texture-creating shader which fixes the problem, then change the "Hidden/Internal-DepthNormalsTexture" line in DepthNormalsFeature to your new shader. I have gotten a lot of requests to improve outlines and transparency, so I'll look into this for sure when I return to outlines, hopefully soon.
@@NedMakesGames Yes 2021.2, and it only says me in the custom function, that the Name NormalsAndDepthSobel is a undeclared indendifier. I tryed with final and the Version before of the hlsl and also checked i have everything Else but still the Same.
@@NedMakesGames inherit, but did a Couple Tests the function still stays Pink. NormalsAndDepthSobel_half is a undeclared indendifier at Line 182 is the full Error, so but precision Set to half Changes nothing still Same.
@@ussdev1988 You can try renaming NormalsAndDepthSobel_float to NormalsAndDepthSobel_half and see if that fixes it. Changing the precision to single or float might fix it too.
Hi! Are you using Unity 2020.1 or earlier? Unity renamed the "Vector1" property type to "Float" in 2020.2, but they are functionally the same! So, whenever I say to create a float, you can safely create a vector1.
Great tutorial! I have no error messages and from what I can tell, I correctly followed instructions. But I have no outlines, it only displays the base color. Do you have advice for where to look to trouble shoot this issue?
Hi! I would set the outlines output to the base color and then try debugging one type of outline at a time. Try out different combinations of settings on the material, and remember to look at it in the game view, since outlines will often look wrong in the scene view. To make sure your depth normals pass is running, open the frame debugger (windows -> analysis) and look for a pass that turns the screen yellowish.
@@NedMakesGames Thank you very much for your advice! I will try this and let you know if I find where the error was, in case other people encounter the same problem!
@@punxNskinsOi Nope, never found the error. I redid it a few times and then got a teacher to give me his functioning version of the code with some of his own tweaks.
Man you just keep surprising me with your outline vids. Great stuff! I have a question though. What method of outlining you explained is more performant - post-processing outline on the whole screen (few previous videos) or per-object outline with this custom outline "injected" material? For context lets say I want everything outlined in my scene + I use only one material (my custom toon mat with texture atlas containing all scene colors) for all the objects in the scene. If I understand correctly, doing stuff in post-processing makes additional render passes, and doing stuff inside shader/material outputs right away in one pass. So in theory having one material with outlines in it would be better. Would it stay true for large amount of different materials with outlines?
Hi, thank you! I would encourage you to run benchmarks for your specific project, but usually drawing outlines in the shader/material/lit-pass will be more efficient since it doesn't require that last screen blit pass. The only exception would be if you had a lot of overdraw, which shouldn't be the case if your material is opaque.
Maybe you can test it out. I think if you do it with object material, it would run vertex->fragment workflow for each object, so the main work is on GPU. If you do the post-processing, you'd have to save the screen texture in memory first and then send it to GPU and only do the fragment pass. Maybe the part where you get the texture and send it back is costly for the CPU? Not sure though.
@@ThomasChen-ur2gt The render targets in BlitMaterialFeature never actually download to the CPU, it's just working with texture pointers. So, thankfully, that's not a worry!
Could you tell me how to make it work for AR VR device using only single pass instanced? I am using it in Hololens, it does work in multipass but I coud not figure out how to make it work in single pass instanced
Hi! First, I will warn you that these outlines are not very performant on VR since you usually want to avoid screen space effects. If that's OK for you, check out this doc from Unity: docs.unity3d.com/Manual/SinglePassStereoRendering.html
Hi, thank you! I don't have a VR headset to test with unfortunately, but I created this tutorial with lightweight platforms in mind. This method is the most efficient way to render edge detection outlines I know of, and I think it will run well!
Hi! You could try a few things. Only using depth outlines will mostly outline the edges of a mesh. There's also hull outlines, a different technique I go over here: th-cam.com/video/1QPA3s0S3Oo/w-d-xo.html So far, you can't mark seams to be outlined; however, I plan to investigate a technique that would let you do that using a mesh's vertex colors.
I'm getting an error on the custom function nodes that saying "undeclared identifier 'DecodeDepthNormal' I see this is being called by GetDepthAndNormal but it's not included in the code anywhere. Some brief searching online says this is defined in the UnityCG.cginc include file which I have, so I'm not sure why this isn't working properly. I've also done basic sanity checks like looking for typos, but no dice. Any idea what I can do to fix this? Thanks for the tutorial!
Hi! That function is contained in the "DecodeDepthNormals.hlsl" file which you can download from the video description (this could be a typo, but note the 's'). The code is indeed taken from "UnityCG.cginc," but that isn't compatible with the shader graph, which is why I had to separate the DecodeDepthNormal function out. Make sure that "DecodeDepthNormals.hlsl" is in the same folder as the "OutlinesInclude.hlsl" file which you use for your custom function node, or Unity might not be able to find it.
@@NedMakesGames Thanks for your quick response, this did the trick, I had some typos inside of the file. One other thing I'm wondering, for this to work we have to disable the camrea's Depth Textures setting (which I think is what the DepthNormalsFeature.cs file is accounting for, but I'm not entirely sure?), but I'm also trying to add some fog effect down at the bottom of my screen for which I'm following this tutorial: th-cam.com/video/1ZsKBZnbAB8/w-d-xo.html which requires the Depth Textures setting to be turned on. Do you have any advice on how I can think about reconciling this problem? I'm pretty new to all of the shader-based stuff, any advice on resources or directions that I could look into to help bring these two features together? I know it's kind of a big question, and I really appreciate any response you can give. Thanks!
@@squintyjeff no problem! It’s OK to enable the depth texture if you need to, in fact the previous video in this series uses it for higher quality depth edge detection ( th-cam.com/video/74AS5DmLe8w/w-d-xo.html ). I just advise to turn it off for these optimized outlines to save some processing power, but everything should work fine together
Hey Ned! Thanks for the great tutorial. I am using the shader graph to animate some grass, and I was hoping to use this effect. Is there a way to do both? Currently the grass animates, but the outline stays true to the mesh
Hi! Thank you, I'm glad you like it! Sorry, can you take a video of your problem, or a couple of screenshots? I'm having trouble visualizing what you mean. Are you saying the outline doesn't move with the animating grass? Are you using a shader graph for the grass outline, or the render objects technique? (I'm going to sleep after this, so my apologies if I don't answer again for a while 😆)
@@NedMakesGames Here is a .gif of the issue I am having I have tried to do outlines as shown in this video as well as through post processing (also a great tutorial btw). I was able to get a decent effect with post processing, but if there's an easy fix for this issue Id prefer to stick with per object outlines. Thanks for the support! Edit: I was able to fix it. Sorry, not sure how. I must have just missed a detail along the line, and stumbled back over it
First of all: great series. But this is the first one I'm having some strange effect, I copy pasted the scripts so it rather won't be their fault, I also double checked the shader graphs and they seem ok, maybe they aren't but until now I haven't found mistakes... Strange effect is... I am getting (as it seem) a proper amount of outlines, but they are all... wait for it... vertical! Without any respect to the actual positioning of the primitives :) Any ideas what I might have done wrong or what I might have not done? :D
That's funny, like it's not detecting horizontally oriented edges? My first instinct would be to check the sobel weights and make sure I didn't accidentally write a float where float2 should be. But if you copied the scripts... Maybe check that the depth normal pass is working. What does it look like if you route the depth normal into the base color field? What about depth?
@@NedMakesGames thanks for the hint, I'll check them later. The funny thing is, that not only it lacks horizontal lines, but all lines are drawn as perfectly vertical, but it can be seen that the amount of lines is correct, and that they correspond to visible edges on the object :)
@@adamodimattia That is pretty funny. That could mean it has something to do with the screen UV passed into the outlines subgraph. Maybe make sure the ScreenPosition node is in default mode.
@@NedMakesGames Well, I solved it. Even funnier stuff. First I check whether depth normals are working. They did. Then I thought, that it had to do with UV and screen position but all was correct. Apparently. I thought, maybe the variable is not passed right, so I went to sub graph and plugged everywhere directly the screen position node. I worked. So now I look why didn't it work from master graph, I look at the variable intensly and my jaw slowly falls down... I made ScreenUV variable as a float! However, I didn't check for a mistake like this, because wouldn't expect that shader graph would have let me plug a float type variable into a Vector2 type variable slot. Not even a warning :) So that's the story. Thanks again Ned for your priceless assistance and time.
@@adamodimattia Oh gosh! Yeah, it would be nice if they made type casts a little more obvious to help find problems like this! Well, I'm glad its working now!
I have done literally everything and have no errors, but am just getting a white body with no black outline. I even made sure to set the mode from overlay to overwrite.
Hmm, that still seems like the outlines aren't blending with your shader's base color. If you'd like, feel free to take a screenshot of your graph and I can take a look. You'll have to either email me or join my Discord and post them, since TH-cam doesn't give me notifications for posts with links.
I'm not sure how this supposed to help in terms of performance if the shader is still too much expensive itself + outlines. On mobiles you for sure gonna lose -50 fps if not more
Is it possible to not draw outlines on far objects? (you said that with large far clip place distant object will draw incorrect outlines) Or "far" is hard to define in a shader.
@@arsenbabaev1022 Hi I’m glad to help! Yeah, just keep raising the far thresholds and they should disappear. If you want, you can set the threshold to a very high number if the depth is greater than some value, maybe using a step node.
Is there no github repository for this? It's extremely annoying trying to follow this tutorial only to get a different result and then spending hours going back and forth in the video trying to figure out where I went wrong.
When created the NormalsAndDepthSobel function, I had to change the Precision of the subgraph to 'Single' to avoid an error.
Thanks, it works for me as well in Unity 2022.3
I learn so much from your videos, thanks so much Ned!
Excellent! I will try to apply this with different kernels / operators than Sobel.
One slightly annoying thing is that the outline is amplified where objects are overlapping (one behind the other) in the view. The effect is even more prominent when the outlines are different colors, essentially picking "false" edges for occluded objects. This is most likely a byproduct of the edge detection + Screen Position, since there is a much clearer difference in intensity at the overlapping points. Couple that with different outline colors and the effect goes wild. This seems like a hard problem to tackle.
An ideal theoretical solution would be to draw the objects one by one, starting from the farthest and performing edge detection on a single object a time, then overlapping the results. This seems like a pain in the ass and the most un-optimized solution ever (at least for Unity, things may be different if one codes it from scratch).
I'm actually not noticing the effect on your previous videos that aren't object-based - Granted, it is harder to notice since the outline is one color.
Hi! Yeah, this is difficult to solve. It's due to the outline only rendering on top of it's mesh, so the part of the outline that resides outside the object isn't rendered. This isn't a problem when the algorithm is run over the entire screen, since the shader can happily draw wherever it wants to.
@@NedMakesGames Hello, thanks for the reply! I'm going to try render Layers and (probably) replacement shaders to emulate per object outline. It might be doable. Also, why is it that a render feature running only once is heavier than running the edge detection per object? Is adding a render feature as post processing that much heavier than running the detection multiple times?
@@CSPlayerDamon No problem! I hope your project goes smoothly!
Post processing is really only an issue on mobile platforms. Memory access can be slow and post process effects require that you copy the screen texture back and forth in a buffer. Then, of course, post processing runs over the entire screen, instead of just the meshes to be outlined. This can be a big problem when the GPU is already busy. It's even worse in VR, since post processing has to run once for each eye.
Amazing tutorials as always Ned! Love your work, one of the absolute best.
I was curious if you think you'd be able to cover water one day. Specifically how game devs handle above water and separate under water rendering, as well as the meniscus. That was always something I wanted to learn about.
Thank you so much! Glad you enjoyed it!
I’m definitely planning multiple series on different aspects of water rendering. I’ll keep your request in mind!
Hi - really clear and easy to follow tutorials, thanks !
I don't understand the value of the matrix at 3:00. If you are using the Sobel operator, the matrix should be:
1, 0, -1
2, 0, -2
1, 0, -1
for horizontal edge detection, as shown in your code at 3:17.
What am i missing?
A problem with this is that the outer outline only eats into the object when it should also expand out of the object. This makes the outer outlines thinner and makes weird artifacts when objects overlap.
I couldn't think of a way to solve this. So maybe backface culling is the way to go for per object outlining.
Or maybe we can combine the two? Because edge detection does seem to work better for inner outlines.
@@ThomasChen-ur2gt Yeah, this is a disadvantage of this system, and it's tough to avoid. You would have to calculate if an outline is in the interior of an object and then use a different thickness. You could probably do this by calculating depth sobel once with high thickness, using that to adjust the outline thickness value, and calculating depth and normal sobel again for the actual outline. But that wouldn't catch objects overlapping. Hmm...
It would be interesting to try hull and edge detection together!
@@NedMakesGames Conceptually what they did is that they only use the interior edge texels for the sobel filter, which makes the silhouette lines behave like inner lines!
Working in 2021.3. After changing *_float to *_half, changing precision to Half, I got rid of identifiers errors. Maked sure the Blend-node was set to Overwrite, but still no outlines, just the plain Base color. Am I missing something?
Those are the two most common errors. You can try routing individual parts to base color to see if they make sense. I can also take a look at your graph if you'd like to post a screenshot. (I would recommend emailing me or posting to Discord, since TH-cam tends to hide comments with links.)
@@NedMakesGames Thank you for willing to look into this. But while making screenshots for you, I noticed 2 mistakes on my side, one in the SobelFineTuning and one in the Outlines. After fixing them, the outlines appeared! Looks like it's working as hoped although further tweaking may take some time. Thanks for your great tutorials and service on this!
@@hermangroeneveld4395 Hey! I'm having the same problem with the outlines not appearing, how did you fix it?
@@dontassumably3603 I fixed it by realy, realy carefully checking every node. It were just 2 sloppy mistakes. I think it was a wrongly connected node at SobelFineTuning and I forget to set a value somewhere. Pretty noobs mistakes... But just staying patient while checking nodes did the trick eventually
@@hermangroeneveld4395 Thanks for replying :O I see I'll look through mine again, Thanks!
oh solid - I get to learn how to latex!
Nice Job!
Still trying to make this shader work for my VR project. Shader looks fine (real fine!) in Unity, but on the Quest 2 it gets 'glitchy'. I hope to fix that/make it acceptable with different settings of the parameters. The main problem now is when I try to bake the static objects in my scene, the objects with the ToonOutlineShader turn completly black. A few static objects with URP Simple Lit Shaders behave like expected, the ToonOutlineShaded objects aren't. Is this shader just not suitable for being baked Lightmaps or am I missing something?
Hmm, which version of Unity are you using? I have not seen that, but Shader Graphs can act strangely with baked lighting.
This effect is just difficult to get working on the Quest. It's very expensive to use full screen textures, like the depth-normals texture. The glitchyness could be from low frame rate. Do you see that in a super simple scene?
Sometimes float precision can be an issue. You can try lowering the camera's far clip plane to improve that.
Works. Unfortunately, in my terrain (procedurally generated) it shows some artifacts, random dots here and there detected as edges. I am guessing it happens where 2 terrain chunks meet. Looks like unity has random 1-pixel holes in the depth texture.
That's unfortunate! I would like to revisit outlines to try to fix a bunch of these strange edge cases, so I'll add this to my list.
Hello, for some reason i have an error where only the Normal outlines are forming, while the depth outlines not
Hi, i have problem when i'm trying to combine it with dissolve shader. I'm using alpha clip to dissolve mesh and it works fine with outline until there is other object with outline behind it. The part of outline that should be invisible is now visible on the mesh behind it.
Hi!
Outlines in general are tricky to get working with transparency. I think Unity's "Hidden/Internal-DepthNormalsTexture" shader doesn't take alpha clipping into account, which can produce these kinds of results. You could write a custom depth-normals-texture-creating shader which fixes the problem, then change the "Hidden/Internal-DepthNormalsTexture" line in DepthNormalsFeature to your new shader.
I have gotten a lot of requests to improve outlines and transparency, so I'll look into this for sure when I return to outlines, hopefully soon.
You should have more subs
Thank you, I appreciate that! I'm working on it!
seems not to work in 2021. have problems with the custom function from outlinesinclude. says me the name wrong indentifier. any idea?
Hmm, what version are you using, 2021.2? Also, what is the full error?
@@NedMakesGames
Yes 2021.2, and it only says me in the custom function, that the Name NormalsAndDepthSobel is a undeclared indendifier. I tryed with final and the Version before of the hlsl and also checked i have everything Else but still the Same.
@@ussdev1988 In your graph settings, what is the precision set to? Helf, float, or something else?
@@NedMakesGames inherit, but did a Couple Tests the function still stays Pink. NormalsAndDepthSobel_half is a undeclared indendifier at Line 182 is the full Error, so but precision Set to half Changes nothing still Same.
@@ussdev1988 You can try renaming NormalsAndDepthSobel_float to NormalsAndDepthSobel_half and see if that fixes it. Changing the precision to single or float might fix it too.
Hello , at 4:36 , my node won't let me create a float , just vector 1 , what should i do?
Hi! Are you using Unity 2020.1 or earlier? Unity renamed the "Vector1" property type to "Float" in 2020.2, but they are functionally the same! So, whenever I say to create a float, you can safely create a vector1.
Great tutorial! I have no error messages and from what I can tell, I correctly followed instructions. But I have no outlines, it only displays the base color. Do you have advice for where to look to trouble shoot this issue?
Hi! I would set the outlines output to the base color and then try debugging one type of outline at a time. Try out different combinations of settings on the material, and remember to look at it in the game view, since outlines will often look wrong in the scene view. To make sure your depth normals pass is running, open the frame debugger (windows -> analysis) and look for a pass that turns the screen yellowish.
@@NedMakesGames Thank you very much for your advice! I will try this and let you know if I find where the error was, in case other people encounter the same problem!
@@singingstranger2571 did you find a solution? i seem to have the same problem. base color only, no outlines..
@@punxNskinsOi Nope, never found the error. I redid it a few times and then got a teacher to give me his functioning version of the code with some of his own tweaks.
I have the same issue. It only displays base color. I'm wondering if I need to enable depth/normal textures in the camera or something similar.
Man you just keep surprising me with your outline vids. Great stuff!
I have a question though.
What method of outlining you explained is more performant - post-processing outline on the whole screen (few previous videos) or per-object outline with this custom outline "injected" material?
For context lets say I want everything outlined in my scene + I use only one material (my custom toon mat with texture atlas containing all scene colors) for all the objects in the scene.
If I understand correctly, doing stuff in post-processing makes additional render passes, and doing stuff inside shader/material outputs right away in one pass. So in theory having one material with outlines in it would be better. Would it stay true for large amount of different materials with outlines?
Hi, thank you!
I would encourage you to run benchmarks for your specific project, but usually drawing outlines in the shader/material/lit-pass will be more efficient since it doesn't require that last screen blit pass. The only exception would be if you had a lot of overdraw, which shouldn't be the case if your material is opaque.
Maybe you can test it out.
I think if you do it with object material, it would run vertex->fragment workflow for each object, so the main work is on GPU.
If you do the post-processing, you'd have to save the screen texture in memory first and then send it to GPU and only do the fragment pass. Maybe the part where you get the texture and send it back is costly for the CPU?
Not sure though.
@@ThomasChen-ur2gt The render targets in BlitMaterialFeature never actually download to the CPU, it's just working with texture pointers. So, thankfully, that's not a worry!
Could you tell me how to make it work for AR VR device using only single pass instanced? I am using it in Hololens, it does work in multipass but I coud not figure out how to make it work in single pass instanced
Hi! First, I will warn you that these outlines are not very performant on VR since you usually want to avoid screen space effects. If that's OK for you, check out this doc from Unity: docs.unity3d.com/Manual/SinglePassStereoRendering.html
Great tutorial!!! btw. how performant is this shader on mobile VR platform like Oculus Quest 2???
Hi, thank you!
I don't have a VR headset to test with unfortunately, but I created this tutorial with lightweight platforms in mind. This method is the most efficient way to render edge detection outlines I know of, and I think it will run well!
@@NedMakesGames Thank you for your response!!!
@@PRodi_ Very curious: did you managed to get the outlines working on Quest?
is there a way to outline material borders and/or mark edges to outline? like in blender freestyle
Hi! You could try a few things. Only using depth outlines will mostly outline the edges of a mesh. There's also hull outlines, a different technique I go over here: th-cam.com/video/1QPA3s0S3Oo/w-d-xo.html
So far, you can't mark seams to be outlined; however, I plan to investigate a technique that would let you do that using a mesh's vertex colors.
For drawing lines on mesh edges, it seems more like a wireframe shader rather than an outline shader.
catlikecoding have a tutorial about wireframe shader in default RP. Real-Time Rendering 3rd also has a chapter for that.
@@ThomasChen-ur2gt I said material edges not mesh edges thou
I haven't been able to get this to work for VR... anyone got any ideas?
I'm getting an error on the custom function nodes that saying "undeclared identifier 'DecodeDepthNormal' I see this is being called by GetDepthAndNormal but it's not included in the code anywhere. Some brief searching online says this is defined in the UnityCG.cginc include file which I have, so I'm not sure why this isn't working properly. I've also done basic sanity checks like looking for typos, but no dice. Any idea what I can do to fix this? Thanks for the tutorial!
Hi! That function is contained in the "DecodeDepthNormals.hlsl" file which you can download from the video description (this could be a typo, but note the 's'). The code is indeed taken from "UnityCG.cginc," but that isn't compatible with the shader graph, which is why I had to separate the DecodeDepthNormal function out. Make sure that "DecodeDepthNormals.hlsl" is in the same folder as the "OutlinesInclude.hlsl" file which you use for your custom function node, or Unity might not be able to find it.
@@NedMakesGames Thanks for your quick response, this did the trick, I had some typos inside of the file. One other thing I'm wondering, for this to work we have to disable the camrea's Depth Textures setting (which I think is what the DepthNormalsFeature.cs file is accounting for, but I'm not entirely sure?), but I'm also trying to add some fog effect down at the bottom of my screen for which I'm following this tutorial: th-cam.com/video/1ZsKBZnbAB8/w-d-xo.html which requires the Depth Textures setting to be turned on. Do you have any advice on how I can think about reconciling this problem? I'm pretty new to all of the shader-based stuff, any advice on resources or directions that I could look into to help bring these two features together? I know it's kind of a big question, and I really appreciate any response you can give. Thanks!
@@squintyjeff no problem!
It’s OK to enable the depth texture if you need to, in fact the previous video in this series uses it for higher quality depth edge detection ( th-cam.com/video/74AS5DmLe8w/w-d-xo.html ). I just advise to turn it off for these optimized outlines to save some processing power, but everything should work fine together
@@NedMakesGames Ooooh okay, that's great news. Thanks!
Hey Ned!
Thanks for the great tutorial. I am using the shader graph to animate some grass, and I was hoping to use this effect. Is there a way to do both? Currently the grass animates, but the outline stays true to the mesh
Hi! Thank you, I'm glad you like it!
Sorry, can you take a video of your problem, or a couple of screenshots? I'm having trouble visualizing what you mean. Are you saying the outline doesn't move with the animating grass? Are you using a shader graph for the grass outline, or the render objects technique?
(I'm going to sleep after this, so my apologies if I don't answer again for a while 😆)
@@NedMakesGames Here is a .gif of the issue I am having I have tried to do outlines as shown in this video as well as through post processing (also a great tutorial btw). I was able to get a decent effect with post processing, but if there's an easy fix for this issue Id prefer to stick with per object outlines. Thanks for the support!
Edit: I was able to fix it. Sorry, not sure how. I must have just missed a detail along the line, and stumbled back over it
@@NotMitch110 Oh no problem! Glad it's working
First of all: great series. But this is the first one I'm having some strange effect, I copy pasted the scripts so it rather won't be their fault, I also double checked the shader graphs and they seem ok, maybe they aren't but until now I haven't found mistakes... Strange effect is... I am getting (as it seem) a proper amount of outlines, but they are all... wait for it... vertical! Without any respect to the actual positioning of the primitives :) Any ideas what I might have done wrong or what I might have not done? :D
That's funny, like it's not detecting horizontally oriented edges? My first instinct would be to check the sobel weights and make sure I didn't accidentally write a float where float2 should be. But if you copied the scripts... Maybe check that the depth normal pass is working. What does it look like if you route the depth normal into the base color field? What about depth?
@@NedMakesGames thanks for the hint, I'll check them later. The funny thing is, that not only it lacks horizontal lines, but all lines are drawn as perfectly vertical, but it can be seen that the amount of lines is correct, and that they correspond to visible edges on the object :)
@@adamodimattia That is pretty funny. That could mean it has something to do with the screen UV passed into the outlines subgraph. Maybe make sure the ScreenPosition node is in default mode.
@@NedMakesGames Well, I solved it. Even funnier stuff. First I check whether depth normals are working. They did. Then I thought, that it had to do with UV and screen position but all was correct. Apparently. I thought, maybe the variable is not passed right, so I went to sub graph and plugged everywhere directly the screen position node. I worked. So now I look why didn't it work from master graph, I look at the variable intensly and my jaw slowly falls down... I made ScreenUV variable as a float! However, I didn't check for a mistake like this, because wouldn't expect that shader graph would have let me plug a float type variable into a Vector2 type variable slot. Not even a warning :) So that's the story. Thanks again Ned for your priceless assistance and time.
@@adamodimattia Oh gosh! Yeah, it would be nice if they made type casts a little more obvious to help find problems like this! Well, I'm glad its working now!
I have done literally everything and have no errors, but am just getting a white body with no black outline. I even made sure to set the mode from overlay to overwrite.
Hmm, that still seems like the outlines aren't blending with your shader's base color. If you'd like, feel free to take a screenshot of your graph and I can take a look. You'll have to either email me or join my Discord and post them, since TH-cam doesn't give me notifications for posts with links.
I'm not sure how this supposed to help in terms of performance if the shader is still too much expensive itself + outlines. On mobiles you for sure gonna lose -50 fps if not more
Thanks!!!
Will this work for 2019.4 and URP 7.5.3?
I have not tested it, but I think it will. Your graph will look a little different, since they changed the UI in 2020.2.
You just saved my game from looking like boring crap (default unity rendering sucks).
Is it possible to not draw outlines on far objects? (you said that with large far clip place distant object will draw incorrect outlines) Or "far" is hard to define in a shader.
@@arsenbabaev1022 Hi I’m glad to help!
Yeah, just keep raising the far thresholds and they should disappear. If you want, you can set the threshold to a very high number if the depth is greater than some value, maybe using a step node.
Hey can you make shader like the one in character in genshin impact?
Hi! Kind of like a soft toon shader with colored outlines? That would be fun, good suggestion!
😻😻😻😻😻
Is there no github repository for this? It's extremely annoying trying to follow this tutorial only to get a different result and then spending hours going back and forth in the video trying to figure out where I went wrong.
Hi! There are links to GitHub sample scripts in the video description. I definitely feel your pain.