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.