Wow, I finally understand shaders. All tutorials I found just zipped through the parameters saying "Use this, use that!", but you actually take the time to explain what everything does. This is amazing.
Having faces talking to me in the video for some reason makes me really uncomfortable (I think that's my problem, nothing with you guys) but the rest of the video is wow!!!! There was a lot of effort put into making the tutorial SUPER clear and concise, wayyyy better than just the average screen capture tutorial that you see everywhere. This was also EXACTLY what I was looking for, all the other "toon shader with shader lab" videos just told you basically to use some already made code without any explanation, and I really wasnt happy with it.... so thank you so much for the videos! I hope they get more attention!!!
Right off the bat. I haven't checked it out yet but looking at your github page I can see that this is a FFing great tutorial to understanding shaders as well. Subscribed!
You guys are awesome! You basically summed up hours of me searching on the web and tinkering with Amplify so quickly. (I never even thought of just sending information from a C# script, I'm kinda embarrassed about that haha)
Thank you! Glad the approach could be used in a different context like Amplify as well, that's awesome! 💪 Don't be embarrassed, not seen any other tutorials do it this way. Though i will not vouch for how performant it would be with a lot of characters in a scene (I've not tested that), but for some games I think this approach can work well. 😊
A faster fix for the subgraph not being found is to open the meta file for the subgraph and paste in the GUID it's expecting (af8ea54a097adc649ac95deb23fbf291). Then it's found and no need to re add and connect it.
Thank you Math Stims! There are many ways to achieve it, think this is a bit of a unique take on it. Maybe not as scalable as other approaches for a game with lots of characters, but very flexible. 😊
@@SnutiHQ It seems like you could create some pretty amazing effects with how well the light colors interact. Thankfully, efficiency isn't quite as important today as it used to be, there's a little wiggle room :)
Pink usually indicates that the shader is not supported by the render. This shader is made for Unity's new Universal Render Pipeline. Check in your package manager if URP and Shader Graph is updated.
This is one of the best shader tutorials I have seen so far. Btw, I'm a little bit confused, Are you siblings? You both looks identical. Sorry in advance if this comment is awkward or annoying.
Glad you enjoyed the tutorial, thank you so much! 😍 Hehe, we're not siblings, even from different countries! But I guess maybe our likeness did attract unknowingly. 😅
It's possible, but you have to manually add it to the shader, because an Unlit Master doesn't have a normal input like a PBR Master. In the tutorial one of the first nodes added is the "Normal Vector", which is the direction of the surface. As I've not tried it I'm fussy on the details here, but I believe you could add a texture input with a texture sample, then add (or multiply??) that with the "Normal Vector". Might work? 🤔
Hey, thanks for this tutorial. I have a few questions. 1st when i tried to add the dot produc to the color value of the shader its just black and not reacting to the light? Im quite confused about it. I did hook it up to the toon helper script but there is no result. Could you please help me out here?
Maybe turn "Ray casting" off in the helper, if that helps you need to configure the raycasting mask to ignore the objects own collider. There are also a few pointers on the GitHub page that might help.
Hey, thanks for the great tutorial! I am using this in a project using URP 7.3, I noticed that when the awesome toon material is applied to more than one object, the toon helper script will only work for one object. Also, creating a second material from the shader causes the second material to render completely black. Do you have any experience with these issues using the shader? Thanks!
If you check the "instanceMaterial" option in the helper script it will instance the material for each object, so each object will have unique lighting properties. I've not seen the black issue, unless your missing the helper script, so no lighting data is set. Or if you got RayCasting enabled and it's colliding with the object's own collision mesh (need to set "Raycast mask" to ignore the object's own mesh layer). Take a look at the read me on github "Shade detection doesn't work".
Rendering issue during the dot product? Using Unity 2019.3.9f1? 7:22 When you assign the same material to both the Mesh Renderer & Script for some reason it doesn't capture the direction lighting being passed. I was only able to see results when I assigned the material only to the script and unity autofilled the mesh renderer as "Instance of Suzzanne Material".
I assume you are using the new version of the script we updated earlier this week from GitHub. When editing the material it's best to turn "Instance material" checkbox off while doing changes to the source material, then when your happy with your changes re-enable it. The script takes a copy of the source material, and assigns it so many characters can share the same source but have individual lighting parameters. Also possible to tweak the script a bit to just have this behavior in play-mode, and not worry about it in edit mode if you find it gets in the way.
Does the object have a collider on it? Then the raycasting might be colliding with it. Try turning the raycasting on the helper off, then configure the raycasting mask to ignore it's own collider.
I'm following the tutorial currently in the newest version of Unity. Its not blending multiple colors together. The directional light makes it glow and it doesn't blend other colors. Any solutions?
I tested in 2019.3.8f1 a few days ago and worked well. This is only part 1 of the tutorial, which is setup with only 1 light (13:50), to support multiple lights you make the main part into a subgraph and repeat it for each light, which is shown in part 2. You can also download the finished shader from GitHub, but you must reconnect the sub-graph, like the "Troubleshoot" section there shows.
If the raycasting is enabled, the "inView" value is checking if there is no obstructions (like a wall) between the object and the light source. This is to enable and disable a light source when it's occluded. It's using a float value to create a smooth transition from on to off, which is defined by the fadeSpeed. It gives the effect of receiving shadows, while not actually doing it, as it's an unlit surface. - I've recently noticed that the game Genshin Impact actually does this exact technique with their characters as well, but then represent this inView as a boolean so it's an instant flip instead of a fade duration.
Finally, I've customized the shader graph in order to work for me instead of multiplying a texture on a gradient I used the gradient to mask two textures shadow and light, but I've screwed up the other lights they don't affect the character only a single one sunlight, I guess I need to fix that later.
Will this work in HDRP? Im noticing that when I select AwesomeToon shader for my material, I don't get any material options other than a checkbox for 'Double Sided Global illumination'. It does not at all look like you show at 1:45
It theoretically works in HDRP, but the light attenuation calculation must be rewritten to handle Lux/Lumens brightness instead of the classic intensity brightness scale. Strange it shows blank for you, maybe if you downloaded the one from the GitHub repo, be sure to re-link it's sub-shader like shown in the readme. For HDRP might be best to try making the shader from scratch using the principles of the approach. We've not tried HDRP ourselves, so I don't know much about it.
It's a great way to sidestep the issue of Shader Graph having no built-in way to use scene lights, but is the issue still standing in 2021? Toon lighting based only on the main light source is too dull.
Yeah, pretty sure this challenge has not changed recently, seems to be quite common in game shaders. But there might be more optimised approaches to achieve the same result, thought more complex I would imagine (probably custom nodes).
Wow, nice result! Thanks for sharing! I'm making a Toon Shader myself but I'm stuck: I can't seem to get baked lightmaps to work. I applied the baked GI node on the very beginning of my shadergraph flow but without a good result. At 13:40 in this video you mention the Baked GI node and propose to use the node at the end of the workflow. Is there any information about how to implement the Baked GI node out there? I can't find any....
I remember experimenting with the baked option, without any luck unfortunately. Would have expected there to be more details on this now so many years later, sadly I'm not familiar. Hope you figure it out!
Looking up the documentation quickly. Yeah, that does look like a good alternative solution! Maybe also more efficient than instancing copies of the material at runtime.
Not sure what the problem is, need a bit more details. But most issues people face have been resolved in the comments here, so be sure to look around a bit! 😊
@@SnutiHQ Thanks for reply, love your tutorials. So the situation is basically the awesome toonhelper script doesn't show information like in the video. I hope I can post a screenshot here TvT
Try to delete the ambience nodes of the shader, or tweek the "shading darks" and "shading whites" of the material. Some of this is shown in the GitHub readme, take a look there for details (and lots of tips in the comments on this video). 👍
hello, i have a little problem, i'm trying to use a second light, if its directional light it detects the color but with spot and point only give black, can you please help me
Might have to increase the intensity quite a lot for it to have an effect. It doesn't perfectly replicate Unity's attenuation calculation, but usually it's possible to find a balance with the right distance, range, and intensity of the light sources. Also possible to do a few Debug.Log() in the helper script to see what's going on with the lights. If the 2nd light is added at runtime, then you must run GetLights() afterwards to update the lights.
Yes, you can replace the end node and experiment with it. 👍 It does work, might look a bit strange and end up with double lighting. I can look a bit better if you tweak the PBR settings.
Disable the "instance material" option in the helper script while editing the material, and re-enable it afterwards if you are sharing this material across multiple characters that need different lighting data. 👍 See also more troubleshooting help on the Github readme linked in the description.
Hey guys! Thanks so much for all of this wonderful information. I have followed the tutorial to the letter and I can't get what you do at 11:53 to work. I add the multiply and connect everything up to the color output. Then everything goes black but when I raise the intensity of the point light it doesn't do anything. It just stays black. Am I missing anything obvious?
Bit hard to know where the issue is, can be so many things. Do you have the helper script hooked up and configured? We have a good "troubleshoot" section on GitHub which might help. github.com/SnutiHQ/Toon-Shader.
@@SiGrossArt Had an idea: Maybe try to turn the "Raytracing" feature off in the helper script. If that changes it, your character collider must be excluded from the Raycasting mask, as it thinks your character is always in shadow from all lights.
I've tested a bit in HDRP. It does work, but the brightness calculation in the helper script has to be changed. When I tested everything went white/overexposed, as the scene works in lumen with a 10 000 lux brightness sun. Tuning the lights down and disabling the ambient in the shader I got it looking alright. You guys are welcome to fork the repo and make a HDRP version of it. Seems that all lines which handles "light.intensity" needs to be changed, but I'm not sure what the right calculation would be here. Seems that Unity have made a conversion formulas in the "Unity Legacy to High Definition Render Pipeline conversion tutorial" article might work.
Thanks for the shader it's awesome :3. I have one issue with it, I wanted to use it only on characters and have my env lit with a different shader and light set up. So wanted some lights to only affect the things with the character layer. But no matter what cull mask is set to, the shader still picks up the lights. any hint on how to accomplish a layer separation for different set of lights with this shader? I am guessing I'll have to modify the helper script in some way, eg so it only uses a lights with a specific tag or some how contrain the script to only get lights from an array?
Glad you liked it! 😁 Yes, you are right, adding a little tag check on the lights in the helper script will do the trick. 👍 Ad default behaviour is getting all lights at the moment.
@Snuti HQ Hi! I'm having the pink problem also, I have both Shader graph and Universal RP installed. I'm using 2020.1.13f1. Can't get the shader to work ! :( Any ideas?
Hard to say without any errors. 😉 There are lots of good tips in the comments here with various issues which have been resolved, and there is also a "Troubleshoot" section on the GitHub readme linked in the description. 👍
Hi, great tutorial. As you said in the video that the shader should be not be used for the environment materials apparently. Also, to create new materials each time for all models in the game will be daunting and a bit overworked. So, how I get the toon like shader effect on the environment props and everything and also receive shadows normally as I see in your game clip - the shadow of the grass is visible clearly and also has the toon shader like effect. So can you tell me how you did it?
Glad you enjoyed! 👍 The grass is actually the regular Unity detail mesh, no special shader. It tints the colour of the mesh, so looks a bit toony without being truly a toon shader. Our environment in general is built that way, regular materials with flat colors. You can modify this setup a bit to work better for many characters, we had to do that for our game as we wanted lots of little Blue Berries to run around. Changed 4 lines of code in the script: files.snuti.net/bk/img/awesomeToonInstanced.png (We use an array as the input, as we needed to swap material on demand in some cases)
When I use the ambient + add my object goes completely white, I change the colour of the light in light settings and it doesn´t change, anyone knows why this happens?
I want to add that when it goes white It doesn´t change the shading gradient and when I change the material colour it doesn´t change, im using unity version 2019.3.10
Depending on your scene setup, you might not want the ambient part of the toon shader, so just delete those nodes. Also you might want to tweak the "Shading whites" and "Shading darks" properties of the material to get the right balance to fit your scene. Got a few troubleshooting tips on our GitHub as well which might help github.com/SnutiHQ/Toon-Shader
Have you hooked up the helper script, and configured it properly? Also if there is a collider on the mesh, it might be "blocking" the light, so you can tweak the "Raycast mask" to exclude the characters collider. Have a little troubleshoot section on the github which might help: github.com/SnutiHQ/Toon-Shader
This is awesome! I really appreciate you guys sharing this with us, did you guys make your environment with the same shader? because it fits really well with your character art!
That's strange, not heard that has happen before. Might be a compile issue, googling a bit I see that a common solution might be "The first class in the file should have the same name as the filename", so if you've renamed the script that could happen.
Hey, first of all, fantastic tutorial, I had a ton of fun going through it and learned a lot. My big question though: My goal for the project working on right now is to create a shader that can have a similar "toon" effect with the hard light edges, but that can properly receive shadows. i.e, I need my objects to be able to receive partial shadow, and have the shape of the shadow show up on larger surfaces. I've been roaming around google looking for solutions and haven't found any. Do you have any ideas as to where I could look for answers, or even perhaps some potential solutions and/or modifications to the shader from this tutorial?
Hey! 👋 To have shadows on an unlit material is at the moment not possible to achieve with ShaderGraph (and if you make it Lit, it loses the "toon"). It is possible to make if you write your own shader code, but I don't have much experience with that. Start with some generic basic shader coding tutorials and the solution might be quite straight forward I would imagine.
Hey there, very handy tutorial. I am wondering how the SuzanneMaterial is picking up Light 1 Direction automatically? In my case it does not pick up the light which is enabled in the scene? Did I miss something?
Ok found it. In script it says materialInstance.SetVector($"_L{i}_dir", lightSet.dir.normalized); materialInstance.SetColor($"_L{i}_color", color); and my naming was different... it is important to keep ToonShader Light dir and color as it is in tutorial so _L1_dir and _L1_color etc... < just leaving this here if someone will place different naming and will stuck
Great tutorial. You've mentioned a couple of times that this shader is good for characters but not ideal for shading the world. What would you change to use it for the environment?
Sorry for late response. But basically as the character is moving around, the helper script will update correct lighting data which is a bit processing intensive. If things are standing still, you could modify it to only update once on start, or find a different way to pass the lighting data, if you only have 1 static sun in the scene you could even bake it into the shader instead of using the helper script. That is much more ideal for environment.
I'm experiencing a lot of performance issues with this shader (from github) while in the editor, I am using a 2022 version. Would I not have this problem if I go to an older version of unity?
I doubt it would be different. It's a shader which can be intensive if you need the real time shading updates on a lot of objects with many light sources, as using C# to plug in updated shading values every frame is not a very efficient way to do it (but was the only viable approach with ShaderGraph at the time). There might be better approaches now, but we've not been using Unity for a while. The shading part of this shader would remain the same, just need better approach for getting the light source data (position/direction/intensity). Might be possible with custom nodes now, but I've not tried any.
I'm having an issue when following this tutorial. The shader doesn't seem to take in the texture's color. It only references the world's color and the L1_color. I can't compare it against the finalized product(AwesomeToon) as that causes any material created from the shader to automatically default to pink(zero options to import textures etc....). Any assistance?
Hey, I had similar issues. I'm not fully done with the tutorial but if you leave the out light 1 col with the multiplier part (skip 11:40-12:10) then follow along with the texture bits, you should be able to connect the final shading node (sample texture 2d) to the multiplier added at 12:38. Then change the default colour on the shader as shown at 12:47. It doesn't take in external light colour (I don't think) but I reckon its a step forward from the black I was seeing before
Sorry it's a bit hard to debug these things, but usually a good approach is to hook the potentially problematic nodes up to the output (with maybe a remap) so you can see what is going on and find where the mistake is.
Hello! I really appreciate this tutorial as it is the closest I've found to my shading style from Blender, and I am new to Unity. I would like to follow along on the tutorial but the part about the shader helper script confuses me, I managed to find the raw code but I don't quite know how to create the script and apply it to the object material?
The script is added as a component to the same game object that has the Skinned mesh renderer component, then fill out all the fields on the helper component (important to put the material in), then it should start to work. You might want to tweak some things to get it working properly, take a look at the troubleshoot section on github, or read around these comments lots of ideas and solutions here. 👍
Hi! This shader works amazingly and looks awesome (as its name would suggest) but I've run into an issue I can't figure out how to fix. My characters are using Skinned Mesh Renderers with multiple material slots. I've seen on another comment where you said that I'd need to make a simple change to the Init function in the helper script to accept multiple materials, but I can't figure out how to do that? You seem to still be responding to comments on this video to I'm hoping you'll be able to help me out. Any tips would be greatly appreciated!
I've not done it myself, so guessing a little bit. But taking a quick glance at the ToonHelper github.com/SnutiHQ/Toon-Shader/blob/master/Awesome%20Toon/AwesomeToonHelper.cs Everywhere material is mentioned, it needs to be switched to an array, like: [SerializeField] Material material = null; // Becomes ↓ [SerializeField] Material[] materials = new Material[0]; Material materialInstance; // Becomes ↓ List materialInstances = new List(); But it does change a lot of things, as everything got to be looped to be set properly, when setting them you would need to loop through them and assign them to "skinRenderer.sharedMaterials[i]" instead of "skinRenderer.sharedMaterial", so everything will become in plural. Will also need to loop the material updates etc. So not as simple was I first thought.
Hello guys! First of all, thank you very much for this tutorial, it's being very useful in a project that I'm doing for my graduation! I have just one question... I would like to use this shader in my trees, but the leaves are billboards, with alpha. Thus, when I try to apply the material of this shader, the leaves become just green squares. Is there a way to adapt the shader so that I can use in the leaves? Thanks again!
Glad it's useful and good luck with your graduation. 👍 I think it will work if you set the master node's surface type to "Transparent", here is a illustration of how → files.snuti.net/bk/img/awesomeToon-Transparent.png
@@SnutiHQ Unfortunately it didn't work, it just made all the materials a little transparent, but it gave me a light! I remembered that I had made another shader some time ago, that gave me the control over alpha. So I tried to adapt the toon shader with the same nodes that I used in the other shader, aaaand IT WORKED! here's an image with the nodes that I used: imgur.com/wzJgc5C ps: I've created a Vector 1 named "Power lpha" so I can use it to control the alpha intensity :)
Thanks for this ! I only wondered how it could work on a rigged character with a skinned Mesh Renderer, because I believe right now the shader only works with a MeshRenderer component. (Edit : Meaning a character divided into multiple materials inside the SkinnedMeshRenderer )
It works with both MeshRenderer and SkinnedMeshRenderer. If your model requires multiple material inputs it's quite easy to modify the script to assign the material to as many slots as your model needs by tweaking the Init() function. github.com/SnutiHQ/Toon-Shader/blob/master/Awesome Toon/AwesomeToonHelper.cs
The AwesomeToonHelper.cs script will raycast to the lights and check which lights are in view. If your environment have mesh colliders that should work. ...Oh, maybe the "Raycast Mask" property on the script must be set properly as well! We might have been a bit too brief on this in the tutorial I see. 🤔 While this won't create true hard shadows (as it's an unlit material), but you'll get the effect of walking in/out of shadow, like you see at timestamp 00:54. We use this in our current game, "The Life of Mr. Pips" and it seems to work quite nicely. Hope it works! 👍
I would verify the inputs by plugging them straight into the master color and see what data is there, maybe the light data isn't coming through. Make sure the helper script is hooked up, and if you have raycasting enabled that the mesh collider of the toon shaded object isn't obstructed by it's own collider (set the raycasting mask to ignore it).
Depends on number of characters and if you need real time lighting changes. If you don't need real time lighting changes, you can modify the helper script to not update every frame which will save performance.
Depends how much of it you use, and how many lights you need it to support. You can take away lots of features and tweak the helper to make it very performant. All comes down to testing what would work for you.
Hi, great video! I have problem with Baked GI, when I link Baked GI (not with ambient) suzanne doesn't show the custom texture/color anymore and the shader itself looks total white, pls help :(
Sorry, I've not actually used the Baked GI setup myself just the basic ambient. I would try debugging it by only hooking up the Baked GI and get that working on it's own before including it in the rest of the setup.
Have you attached the helper script? If you got the script on and got raycasting enabled, make sure if your character has a collider that it's ignored by the raycaster using the raycasting mask, otherwise it's shadowing itself. Or turn raycasting off if you don't need the fake shadows.
So cool! Now not only I can create a lynel but make it look like the real thing. Thank you very much. The only question I have is how to give it a black outline to achieve comic style effect?
That's awesome to hear, the Lyndel is a majestical creature! 😍 The black outline can be made in various different ways, one approach that is quite popular is to duplicate the mesh and inflate along the normals, then flip the normals and make it black. But it will be twice as many polygons, so not very efficient. Searching you'll find lots of tutorials on various approaches to make an outline effect in Unity.
Toon shading is usually hard edges, but it's possible to make this soft actually using the fading gradient texture that's in the git repo linked in the description.
Hey there! this tutorial was amazing! and the finished product came out better than expected. but I just can't manage to get blacks in my shadows. the darkest i can make them is a mid grey. I need some help lol . amazing job on this tutorial. I learned so much!
Thank you, glad you enjoyed it and learned a lot! 😁 Plenty of love was invested into this, so glad it was helpful. As for your blacks, I'm guessing it's related to the ambient light. On the GitHub github.com/snutihq/toon-shader take a look under "Everything looks bright and washed out", maybe delete both the "Baked GI" and "Ambient" node, those are a bit dependent on your scene setup and how you want it to look and feel. So hope that helps. 👍
Thanks so much for this great tutorial, I hope to use it in a project I am working on. Should I do some kind of crediting if I will use your shaders in my project?
You can download this from the GitHub page linked in the description. It will throw some errors, as you need to re-link some things, but checkout the readme on the GitHub with how to fix that. 👍 But recommend you follow the tutorial and maybe learn a few things instead of downloading it. 😉
I am using Shader Graph with URP and Imported your prebuilt from Github. Problem is that when I create a Material always results in a pink Material. EDIT: Nevermind. I opened the Shader Graph and re saved it.
the shader is awesome! but when i have (for example) a tree in my environment it does not cast shadow on my character..it also does not cast shadow on hes own mesh (on the shoulders) how could i fix this? great tutorial anyway!!
This setup does not receive direct shadows (0:52) as it's using an unlit shader, so you will not see a detailed shadow on the surfaces. To compensate for the lack of shadows it fakes it by checking if the light source is in line of sight (raycast), then fading that light source on and off on the material. I see it's not very well explained in the first minute, sorry about that. I don't think it's possible to make a toon shader with detailed shadows using Shader Graph at the moment, but could maybe be done on a render level in the scriptable render pipeline. 🤔
Bit hard to say why without more details, but did you hook the material up to the helper script input? Also when modifying the material, make sure you disable "instancing" on the script while you do your changes. There is also a few more pointers on the GitHub read me with troubleshooting help.
Using URP I don' think normal maps are supported? 🤔 But this could be maybe customised to use it in HDRP, but that also requires all light intensity calculations to be changed.
Bit hard to say why without more details, but with URP and Shader graph installed, it should be just dobble clicking it. Check for errors in the console. There are also some troubleshooting tips on the GitHub Readme. 👍
@@SnutiHQ wow! what a fast answer! I think Shader Graph was what i missed! I will try it later! Many thanks! Keep up the good work! If you need more video ideas now that ur game is released, i would love to hear ur opinions on Dev Topics like Level Design, Game Name, planning a game and stuff like that! I'm really hapy i found ur channel :3 greedings from Germany!
@@Nebraf RU-vid didn't give us a notification for this reply! 😭 That's so nice to hear, thank you so much. 😁 Maybe join us on Discord and we can have those fun discussions? 😊 snuti.net/discord
Awesome tutorial you two!!! I'm making a game for my thesis project with a very graphic style, and this is gonna help my team so much! You've certainly earned a sub from me!