Fluffy Foliage, Wind and Subsurface Scattering: [Unity Shader Graph and Amplify]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello and welcome back to PolyToots, in  this video we’re going to be creating some   foliage that we can control the scale  of, it also has a basic wind system   and some pseudo sub surface scattering for when the light is behind it. I’d like to thank Pontus Karlsson for his  amazing video on fluffy stylised trees,   I learned a lot from that video, and promise  that this isn’t a total ripoff. But if you’re   interested in billboarded foliage I’ll leave  a link in the description for his video. This shader is available for  both shadergraph and amplify   over on my patreon, but since we covered  shadergraph in the last shader tutorial,   this video will be done in Amplify.  And we’ll be using URP for this. So let’s clear our scene and get started. The first thing we’ll cover is the mesh that  we’ll be using, we do have to make our own but   it’s super easy. You could probably make this  within Unity by using something like Probuilder or   UModeller, the main thing you need to keep in mind  is the mesh must be all quads, and the UV’s must   be mapped to each quad, this can be called face  mapping if you’re unfamiliar, or familiar with it,   not to be confused with unwrapping faces I guess. I’ll be using blender for this and it’s as easy  as starting with a box: subdividing it once,   extrude for the general shape you’re after and  then smooth it out or move some verts around   for the final shape. The grab tool in Blenders  sculpt room helps a lot with this sort of thing. I’m also going to make sure this  mesh has smooth faces, because   unlike Pontus Karlssons video, we’re  not going with a billboard effect so   having smooth mesh normals will work in our  favour. I also want to make sure the pivot   point is at the center of the object,  this will be pretty important later. Next up we need to sort out the UV’s, since  each quad here will represent a piece of   foliage we need to map each quad. Meaning  we don’t just unwrap this object as a whole,   we’re mapping each individual quad to the  0-1 UV space. In blender this is easy,   but first we’ll apply our subdivision modifier  so all of the geometry that we have here is kept,   then hop over to the UV room, select  all your faces and go to UV > Reset.   Done. Now we can export this mesh  out as an FBX and get it into Unity. From here we can get started on the shader,   and again we’ll be using the Amplify editor  for this, but if you’re using shadergraph on   the universal render pipeline then  the setup is pretty much the same. So I’m going to make an amplify  shader, universal, and choose PBR.   You could go the route of using an unlit  shader for this depending on how far away   your foliage is, but having default self  shadowing really helps the visuals on this,   plus you get smoothness and access to normal  maps as well if you wanted to be all super fancy. So let’s start with the quad scattering, which  technically isn’t scattering: but “quad scaling”   just isn’t as catchy. To do this we’re going to  tell the shader that we want to split-and-scale   our geometry based on the UV’s, this is why  all of our quads are mapped independently.   So we’ll start with a UV coordinate node, and  now we need to remap this because UV space goes   from 0 to 1 on the X and Y, meaning 0 is the  bottom left point, and it goes up to 1 on the Y,   and across to 1 on the X. Ideally we want to  scale them at the center. Think of it like   each quads pivot point, we need that pivot to be  at the center of the face, not in the bottom left. So if we change our remap here and leave  everything as default except the new minimum,   you can see that as we go into the negative,  we’re re-positioning that bottom left corner.   And since the old values were 0 to 1,  we need the new values to be -1 to 1,   because now 0 would be in the middle.  I’m pretty sure the preview for that   in amplify is a little offset, but the  math checks out so we can just move on. If we multiply this by a value, (which  we’ll keep for later so I’ll name this   Fluffy Scale and make sure it’s a property), and  then hook this straight into the vertex offset.   You can see that the quads are being split,  but the scaling is a little wonky, also   if rotate around you can see that the backside  is not behaving at all, and if we look at it   from the side you can see it’s only scaling on two  axis. So we need to inject that magical 3rd axis,   and also make sure the quads are staying  in their original object orientation. So to do these two things, we just need one  node in Amplify, the Transform Direction,   which we want to set from Tangent to Object. Since  tangent space is the coordinates for each face,   and object space is the coordinates for  the object. So it’s like we’re saying “hey,   I like what’s going on here, the splitting  and the scaling, all of that is great,   I love it, it’s perfect. But if we could  just apply that same thing in object space,   then that would also be perfect”. And this node  here says “yes” to that, which is, y’know, nice. We also want to normalize this which just helps  keep the scaling intact as we transition from   one space to another. In amplify this  actually doesn’t make a huge difference,   I’m not sure what’s going on behind the scenes  with this node, but in shadergraph this setup   definitely requires the normalize node, and we’d  also have to turn the UV’s into a vector 3 first,   but yeah for some reason we don’t need to  that in Amplify. Which is good, and weird. So now if we take a look at what’s happening,  we’re getting a nice scale across each face,   it’s working in object space too so the  scaling is happening around the whole mesh,   and since this is in object space, we can rotate  our foliage around and everything stays in place.   Very cool. We’re done here for now, we will  come back to this setup to plug the wind in,   but we can safely move onto some back lighting.. Let’s just have a little tidy  up first, I’m going to use   a register node to hook our quad scattering  setup into, call it something that makes sense,   and with everything selected I’ll press  C to group these, move it out of the way,   then create a Get node and get the register we  just made, hook that into vertex offset. done. I’m also going to enable our skybox in the scene,  since the light direction is quite important for   the effect we’re about to make. So important in  fact that the first node we’ll make will be the   world space light direction, and we want to  dot product this with a view direction. The   reason we’re using a dot product is we’re dealing  with two different direction vectors. I’m not an   expert by any means but in this context what we’re  interested in is finding out the direction of two   vectors: Light and view direction, and we just  need to know at what point they’re positive or   negative, for us this would be if the light  is in front or behind our viewing angle.   I’ll throw down a saturate here to stop the  values from going beyond 0 and 1, and get this   hooked into the emission via our old friends  Register and Get, and you’ll see what I mean. As you can see when I change our  viewing angle so the light is behind us,   but in front of the object, it is outputting  a white value. And if we go behind the object   it’s like nothing has changed at all, this  is because we’re saturating the values,   so 0 is as low as it can go, and 0  emission is basically like no emission. So that’s that, and obviously we want the  positive value to appear when we’re at the   opposite angle with the light behind us.  So we’ll need to tell the shader that   the light direcion needs flipping.  And we do that with a negate node. You can see immediately that this is having  the right result. It is a little strong though,   and of course we can come back here and  multiply our light direction by a property   to control its strength, which would do as you  expect, but we can push this a little further   by giving priority to the light  on the outside of the mesh only. We do all of this by multiplying  another transform direction,   and then add that to the light direction  instead. This time our transform direction   is going to go from object to world, so  we’ll hook in a vertex position node.   The reason we do this is we need to know the  vertex position relative to the object origin,   and for us the object's origin, otherwise known  as a pivot point, is its center of mass. So we can   basically use our centre of mass as a mask for our  light. And we have to transform it to world space,   otherwise if we rotated our mesh then the  light would rotate with it. Obviously not cool. One last thing to do here is  to chuck in a bit of colour,   set it to a property, and multiply  it into the chain at the end. I suppose we should probably address the  fact that there’s no texture on this,   obviously the style and content of the  texture you use will drastically change   how your foliage looks,. The texture  I’ll be using is included in the   download of course but I do encourage you to  create your own and experiment with the results. Let’s start by dropping down  a texture node, we’ll also   multiply this by a colour because tinting your  texture is always handy. I’ll register this,   and I’ll also make another register node for  our alpha. We’re going to use cutout alpha   for this. If you’re developing for mobile then  I recommend going with regular transparency,   which might sound a bit backwards, but  we don’t have time to get into that. So I’ll just go get our gets and plug those into  the albedo and alpha respectively. By default   alpha is not enabled and for us we don’t actually  need to enable it here, instead what we’ll do is   create a float down here and plug it into the  alpha clip threshold, which will let the shader   know what we’re trying to do. I set this to 0.5  which is usually the default clip value, but feel   free to turn this into a property and adjust it  on the material if you’re feeling adventurous. I’m also going to add in a smoothness  value here, turn it into a slider   and set the default to 0.3 just because  I don’t want super glossy leaves.   Oh and if you get this error about too many  interpolators, that’s because at the time of   recording, Amplify will default the shader  model to 2, and we’ve hit a bit of a limit   on the amount of instructions we can do, so I  need to change the model over to at-least 3,   which we can do here. And honestly this is  not a problem, even ancient phones by today's   standards support shader model 3, so y’know:  Den Peirazi as they say in the land of Souvlaki. Right, let’s chuck in our texture here, and as  you can see it’s looking mostly fine, the fake   light from the backside is of course just pure  white, since we’re using white as the emission,   we could overlay the light with the texture  before plugging it into the emission,   we can even multiply it with  the light colour itself.   So now even if we leave the SSS colour as white,  it will draw from the colour of our texture and be   influenced by the light colour. Obviously if  you want to keep it simple then just rip all   that out and change the colour manually.  Sometimes the simplest is all you need. If you wanted a more colourful result, what I  tend to do is the laziest thing possible, which   is to just add a HDR range into your initial tint  colour, don’t blast this too high though as it   will obviously be a bit crazy, it also contributes  to the bloom if you’re using it, so yeah, caution. One last thing to mention before  we get a crack on with the wind,   is that you can of course change the tiling  on the texture to get different results. It’s   not a game changer or anything but if you’re  in a pinch and for some reason your boss has   only given you 8 seconds to come up with a whole  new bush, then happy days. Also get a new boss. Okay, so, wind. One common way to do simple  wind on foliage is to alter vertex positions   of the mesh, based on a panning noise  map, so as the noise pans, your verts   go all wibbly wobbly. And that’s exactly what  we’re going to do, with some minor additions. The first thing we’re going to do is  get ourselves some world space UV’s,   and we make this with a world  position node, and append the X and Z,   because those are the coordinates I want  to project from, which in this case is the   vertical axis but It doesn’t really matter which  axis you choose. Since we’re only outputting   a vector 2 I’ll change this append to a Vector  2, and then we can multiply this by a property:   this will be the tiling of our new UV’s and it’s  only going to exist as a property temporarily,   once I’m happy with the size of my noise  I will hide this from the inspector. Now we need something to inherit this, that  will ultimately control our verts. So we’re   going to use a small tiling noise texture, you  can use a procedural noise generator if you want,   both Amplify and Shadergraph have  these, but it’s often a good rule to   steer clear of these if you can replace the  functionality with a tiny texture instead. We do need this to scroll as well, so let’s also  throw in a panner node, and we’ll plug our UV’s   into the panner, and then panner into the textures  UV’s. For the Panners speed I’m going to set the   X and Y to 1, in this context the 1 is just to  enable scrolling in that direction, for the actual   strength of direction we’ll control that with  a classic blend of time multiplied by a value.  At this point we’ve probably got something  worth having a look at, so I’m going to create   a register here, give it a name, and then come  over to the master output and just for previews   sake I’ll get that wind scroll noise, de-hook  our albedo and replace the emission with this. From here we can play with the  noise scale and the scrolling speed.   This is what will eventually affect the movement  of our verts, where white will be the wind,   and black will not. It’s important  to have areas of rest for this stuff,   you don’t want everything jiggling  all the time, that’s just messy. So what I’m looking for here is quite a big  scale, so there will be obvious areas of wind and   no wind, then I can use the scrolling speed  to determine how fast this all needs to be.   I’m happy to leave the scale at 0.1 but  as you can see the speed value is entering   the annoying range. Nobody wants to faff  about with zero point zero numbers, and   we’ll sort that out later when I’m more  certain of the acceptable speed ranges. Back to the shader for now then, let’s put the  previous albedo and emission back in place,   and I’ll grab this get node for the wind and  come up to our quadscatter setup, and add our   wind into the equation via a multiply of a vertex  normal node. This is just us telling the shader   that we want the black and white areas of our  texture to have an effect on the vertex normals. Also before I forget, I’ll  come to the noise scale,   set it to 0.1 and turn it into  a constant. I’m happy to never   adjust this again on the material. But  obviously you can leave this if you want. If we give this a quick save, you’ll see  we’ve got something going on already.   This is nice, but it’s not great, we have an  issue where too much is happening and it’s   difficult to see the areas of rest. One easy fix  for this is to come back to the wind setup here   and chuck in a power node at the end,  and give it a value of maybe 1.5. Now you can clearly see there’s areas that are  not being blown about, and this is much better   in my opinion. We can still do better though.  What if instead of this robotic back and forth   of highs and lows, we introduce a secondary  layer of noise to cause a bit of jiggle? To do this, we’re going to need some differently  scaled noise scrolling at a different speed, so   first of all I’m going to come to our world space  UV’s here, and I want to multiply the output by 2,   which is basically just giving us twice the tiling  amount, and I’ll hook that into a new panner node,   again setting the X and Y to 1. I’ll then make  another texture node and set this to a reference,   and use the original wind texture as the  reference, and hook the panner UV’s into this. Now we just need some different time, and I’ll re  use the time we already have but multiply this by   a new property called Wind Jitter. If we go and  see what this looks like, it’s basically causing   the verts to jitter about a bit whenever the  original wind noise is coming into effect. And   with our new property we can control the strength  of this jitter. And much like with our property   for the scrolling speed, we need to be careful  of what values we use here. So I’m going to   play about with both and work out what my mins and  maxes will be. For example I don’t think I want my   wind scroll to ever exceed 0.1, and weirdly enough  I’ll probably go with the same for the jitter. So back in the shader, I’m going to turn these  properties into sliders going from 0 to 1,   and then remap these values  so that 0 is still equal to 0,   but 1 will equal 0.1. So now  when we come back to the material   in 3 months time we don’t have to worry  about remembering what values work well. I think that’s that, I’m just going to tidy up   the property order on the material  here and get ready to call it a day. So there we are, one more overly lengthy  tutorial to add to the collection.   I hope this has been of some use, remember  that all source files including the shadergraph   version are available over on my patreon, and  of course I cannot thank my patreons enough,   I’m going to have to think of some other  solution to the end credits of my videos   at this rate because there’s so many of you  now. So y’know obviously thank you very much And yeah this is the end of the video, with an  awkward sign off, see you in the next one, bye   bye.
Info
Channel: PolyToots
Views: 36,395
Rating: undefined out of 5
Keywords: unity, sculpting, game dev, texturing, baking, unwrap, uv, game art, shaders, amplify shader editor, tutorial, shadergraph, graph, VFX, Blender, 3d, 2d, PolyToots
Id: flbnFFZWcsc
Channel Id: undefined
Length: 16min 57sec (1017 seconds)
Published: Mon Jun 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.