Fluffy stylized trees tutorial, using quadmesh-to-billboards shader in Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone today i would like to share a technique with you for making foliage that i figured out recently while making these trees for a game that i'm working on so the really cool thing about this technique is that i didn't actually place any of these cards by hand nor did i use any specialized third-party software in order to do any complex setup for this so the way that this technique work is that i've got this mesh that i made for the tree and the shader takes each of these quads and it effectively turns them into a billboard for this tutorial i will show you how we set up the content to work with this technique and also how we do this camera facing shader i won't have time to go through how we set up the wind and the lighting effect for these but hopefully this should give you a good start i will be using amplify shader inside of unity but if you're using unity shader graph for instance or maybe unreal i hope this should translate fairly well so let's start by jumping into our 3d software to see how we set up the model for this i've got my tree model here inside of my 3d software and as you can see this is not a very complex model there are however a few things we need to make sure of if we want this to work well with this billboard approach and the first one being that we want the model to consist out of equally distributed quads meaning polygons with four corners on it and in theory we could do this with triangles as well but the nice thing about a quad is that it maps nicely to the to use the entire texture space and secondly and more importantly we need to make sure that each of these quads use the entire uv space and i'll show you what i mean by that so if i open up the tree inside of my uv view and let's just isolate this so we only have the tree crown here as you can see each of these quads fill up the entire uv space here so from zero to one we fill out this entire thing so each of these uses up the entire thing and another thing that i've noticed gives a lot nicer result is to use hard edges on this model we could do this with without going for hard edges but i've noticed that each billboard gets a single light value if we make this a soft mesh each of the vertices will receive slightly different shading so having the hard edges kind of helps give each billboard a more representative light there is also no extra cost involved since we're already splitting each quad by the uv so this hard edge won't actually add any extra vertices for us so in order to create a mesh like this there are two approaches that i would recommend for doing this the first one if you're doing it inside of a 3d program i would use subdivision and let me just quickly show you why so i've created this new cube and i'm just gonna move it out of place here let's get up a bit so subdivision means that we take a mesh and we split each of the faces twice so we essentially end up with four times the geometry and one really nice property of subdivision is that no matter if we have quads like this or if we have triangles such as this or even if we have let's say a face with five vertices on it if we subdivide this mesh so let's say you build a volume out of some kind of geometry and if you then subdivide this mesh so it's subdivision here everything will be turned into quads so the triangles turn into quads and this big end gone over here this five-sided polygon also gets turned into equally distributed quads to manually unwrap a model like this what i would usually start out doing is doing a projection of some sort so either a planar projection or a view projection just so that all of the faces are represented inside of the uv space so once we have some sort of uvs we can then select all of the edges and cut the uvs by the edges in my case i'm using a hot key here once they're cut we can unfold them or relax them so that all of the faces are separated from each other so once it's separated we can align them and we can use a function called rectangle which will force the uvs to be rectangles but they're still a bit all over the place so next up i will align them so first aligning them vertically and then aligning them horizontally so they're all centered and they're all rectangles so once we have them like this all we need to do now is to select all of these stretch them out and just flatten these by scaling them and then snapping them to the to the borders of the uv so i'll do the same for this one and i'll scale it and then grabbing these scaling and moving it and same for this one so effectively now all of our uvs are unwrapped individually to use the full uv space so this is a really quick way if you want to do it inside of a 3d modeling software however i made this one inside of zbrush and i'll show you why that is a really nice approach so let me open up zbrush here and i've got the tree in here as well so as you can see i've sculpted these pieces and when you sculpt this geometry you can really go crazy with your style you can experiment a lot and once we have this mesh looking the way we want it to we can then use a feature in c brush called c remesher so inside of zbrush under geometry we have this thing called serial measure and serum measure takes whatever geometry we have and creates a quadrangulated mesh from it so in here we have a few options and one being the adaptive size and the adaptive size tells zbrush how much it should tolerate rectangles so whether or not we allow it to create long thin triangles and in my case i've just set this to zero feel free to experiment with this there's also a target polygon count meaning how how many triangles do you want to end up with and obviously the higher the polygon count the more expensive the mesh will be to render so feel free to experiment with this as well so i'm just going to hit serial measure and it takes my sculpt and it creates this nicely nicely distributed quad mesh so one more nice thing about zbrush is the way we can unwrap this in the way that the shader wants this so again in zbrush there is under uv map we have the option to create a new uv map for this so under review map and create there is a thing called the uv tile and clicking this creates a new uv that places these exactly how we want them and it's kind of hard to preview this in zbrush but if we click this morph uv button the faces will be morphed into their corresponding uv position giving us an indication that the uvs are laid out correctly i've got this new project set up with just these two models and a direction light in it that i will be using to try out our new shader while we build it and i'm going to start by creating the the actual shader by right clicking inside of the project i'm going to create and i'm going to make an amplify surface shader for this and let's name this foliage shader and we're also going to need a material that is using this shader so i'm going to right click once again and go to create and take material and let's name this voltage 01 we also need to make sure that this new material is actually using the foliage shader so up here in the material we can change the shader to foliage shader there we go i also need to make sure that the models are using the new material so i'm going to drag drop these onto here like so and now we're good to go the data that we'll be using will be the actual uvs on the vertices and in order to access those we need to grab a note called vertex text chord so this one contains the u and v coordinates for each vertex and just to visualize what this data looks like i'm going to plug this into the emission channel and i'm going to hit compile so looking at the model now we can see that each of these quads is using the 0 to 1 in uv space so the red one is the u axis and the green one is the v axis we can also think of these as x and y and i'm going to use this data to create a vertex offset if you've never done a vertex shader before or played around with vertex offsets you can think of it as a way for the shader to change the position of a vertex before it's being drawn onto the screen so the shader has access to all the information about the models that are being drawn onto the screen but before actually drawing out the triangles as pixels it has the ability to manipulate those values effectively just moving the vertices and the best way to visualize this is to just create a new vector so i'm going to create a vector 3. so three values and this is exactly the same as you would use position in your scene so you have the x y and z value and i'm just going to plug this directly into the local vertex offset and if we want to change these values in the material itself we also need to make sure that this vector is not a constant but it's actually a property so looking up in the left corner here we can see that this one is said to be a constant so changing this to be a property and we can name it something just so that we can see it more clearly so i'm going to call this offset and i'm going to hit compile so so far nothing has happened and that's because our offset is set to zero but if i select our material you can see in the inspector now we have this option here called offset and if i change one of these values so let's say i change this x value you can see that the vertices appears to move to the side here and we can always change the y value and the set value but the cool thing about a vertex shader is that the underlying model is actually intact and in unity we can see this quite clearly if we select the model so we can see here that the outline is outlining the original model whereas the geometry being drawn out is offset to the side here but i'm going to get rid of this because we're not going to do it this way however we are going to use these uv text cord this vertex text cord to drive the offset so what would happen if we just plug this directly into the local vertex officer let's give it a go so looking at the model now it sort of already looks like the thing we're going for we have each of these quads more or less facing towards us so what's actually happening here is that for each vertex it's looking up its uv value and if the uv is set to zero like it is here you can see that it stayed in place this is actually matching the outline here so this is the original location of the vertex whereas where the vertex is where the uv is green for instance it has moved one unit in the y-axis and where it is red it has moved one unit in the x-axis so this is sort of what we'll be doing however if we look if we zoom out a bit we can see that the everything is kind of going diagonally upwards and the reason for that is because we're adding one in x and one in y so we're effectively moving it up and right so the first thing we need to do is to make sure that the the lower left corner wouldn't stay in its place that it but rather going left and downwards instead so we need to remap this value so currently the uv goes from zero to one but what we want to do is that we want the right hand side to go as it is now but the left hand side should go in the opposite direction so negative one the easiest way to do that is by using a remap node so i'm going to type in remap and grab one of those so the remap node it takes a value and it scales it so we can say what the uh what the old minimum value is and then we can set a new minimum value effectively stretching the vertex so i'm going to plug this uv in here and by default the remap node when it's added a second channel here it actually didn't fill in the same value as the first one was so we can see here the maximum old is set to 1 for the x but 0 for this so we want the maximum old to be one so the old value should be the value that we currently have so we have a uv that goes from zero to one in both x and y but the new minimum value instead of being zero we want this to go towards negative one and same with the y to negative one and the max value should still be one so we need to make sure that this one is one as well like so and let's plug this in so now we can see that the uh the quads are um equally distributed to the top and to the side so it's no longer pointing towards the top right so again this looks sort of what we're going for however if i turn the camera you can see that it's not actually caring about the camera it's just pointing locally up and to the right it doesn't it doesn't know anything about the camera so the next thing we're going to do is to force these to look towards the camera to make the quads face the camera we're going to take our uv-based offset and we're going to transform it so that it is relative to the view of the camera which is also referred to as view space to do this i'm going to grab a node called view matrix the view matrix holds information about the camera that is currently rendering the scene or rather it holds the position and orientation of the inverse of the camera meaning what the camera is currently seeing if we multiply our uvs with the view matrix we're effectively transforming them to the view space so i'm going to add a multiply node this one and i'm going to multiply this scaled uv with the v matrix however this will not quite work so looking at it now we can see that it's doing something it sort of shifts a bit in place but the reason this is not working is because the vector we plugged in is a 2d vector we only have the u and the v value so we need to make sure that this is actually a 3d vector and to do that i'm going to use a append node so right click and type append so i want to create a vector3 so in the node itself we can set the vector type it's by default it's set to vector4 but we're going for a vector3 and i'm going to plug in the scaled uv and automatically it fills the x and y value however the set value is set to 0. and that's exactly what we want uh just be zero because we're not interested in the set value and we can see now that the lines going into this node has two lines meaning it's two values coming in but when we grab it from this side we can see three values going out so we've effectively turned our 2d vector into a 3d vector so once i plug this in here and hit compile these are now facing the camera so this is exactly the effect we're going for however there is one little problem with this or actually two little problems with this the reason this is actually working now is because i haven't changed the rotation of this so let's say i spin this now we're always facing the side of the quad the reason this is happening is because our offset is being applied relative to the orientation of the tree model itself which is known as object space or local space to fix this we need to take our offset and transform it so that it's using the object's orientation in the scene instead which is known as world space the easiest way to do this is to grab another matrix node and i'm going to use one called the object to world object to world matrix and same as before i'm going to multiply this uh our vector with this new matrix and i'm going to create another multiply node we can do this quickly by just holding down m and clicking so i'm going to grab this and i'm going to multiply with a vector with a matrix and i'm going to plug this into the local vertex offset so the effect is now supporting rotation so no matter how i rotate this uh all the quads are always facing the camera however once again we've missed one little thing so what would happen if i scale this model so you can see that the quads are not consistent when we scale this object and that is due to the the length of this vector so in order to make this vector a uniform length um so it doesn't go off like this when we scale it i'm going to use a normalized node so i'm going to right click i'm going to type normalize and i'm going to plug this in so now the tree supports rotation and it also supports scaling so this means that the camera effect is now actually working so let's get rid of this uv in a mission and let's instead use this pbr material that we already have set up here so i'm going to create an albedo value by creating a vector 5 which is used for colors so i'm going to hold down 5 i'm just going to click so this is a vector five and we can set it to a color so i'm gonna pick some sort of green shade for this um the alpha is actually irrelevant but i like seeing the color in this viewer so let's just go for some shade of green and plug this into the albedo so what we're seeing now is the quads are pic they keep the original lighting that the underlaying mesh had so to visualize this i'm going to create this blend effect that i had in my in my own example so that we can switch between the billboard version and the non-billboard version and all we need to do for that is to create a lerp so i'm gonna hit lerp so the lerp is just um two values uh that we blend linearly by plugging in a third value that controls which one of the two values we see or how much of each of these two we see by plugging in a value between zero and one so when this is set to one i want to see this effect and when it's set to zero i want the offset to be zero which we already have here and i'm just gonna create a value that controls this alpha i'm gonna hold down one and i'm gonna click so we'll get a float and just like before i don't want this to be constant i want to be able to access this inside of the material so i'm going to change this from a constant to be a property and i'm going to call this um effect blend like so and i'm going to plug this in as the alpha i also want to make sure that this value when we slide it it won't go below zero and it won't go above one and in amplify if we want to make sure that a property stays within range we can set a minimum and maximum value but if both of these are set to zero it means that we can slide it however we however we like so we need to set a maximum value here so i'm going to set this to one and you can see this instantly updates to a slider so let's just plug this back in and set the default to one and compile so selecting the material now we have this slider called effect blend and if i slide this towards zero we can now switch between the initial model without the offset and the billboard effect with a full offset so the really cool thing about this method is that uh if we look at this value that we have here like for instance let's look at this um dark quad down here once i slide this actually it went heading but hidden but the quad itself keeps the shading from the um from the original mesh so with vertex shader this is actually a positive side effect because whenever we change the position in a vertex shader we don't update the normals by default so if we would like the billboards to get their shading as if they were actually placed the way they were on screen we need to do that calculation ourselves but in this case we don't want that we want the original shading so this is just this is perfect as it is however we might want to make this look less blocky so i'm going to add a alpha to this so i've already prepared an alpha that i've used in my own trees and the reason this is red and not white black and white is because it's said to be a single channel meaning i get the red channel so think of this as a black and white image being our alpha so i'm just going to drag drop this in here and i'm going to plug this into the opacity mask however this shader does not yet support alpha so i'm going to select the shader and under render queue i'm going to change this to be alpha test so now we have the option to set an opacity mask we also have a few extra options that are only for transparent object and not the alpha test object so i'm also going to change the render type to be transparent cutout so now we only have the opacity mask available so i'm going to grab this red channel i'm going to plug it into the opacity mask and the reason it didn't update is because these texture samples are by default a property meaning that the material can override this the texture that we have set inside of the shader itself so we need to go to the material and we need to set this texture in the material as well there we go so as soon as we apply the alpha it instantly gets really fussy um it's also worth pointing out that something i've noticed with the alpha is that it really helps a lot to have quite a high frequency of detail so uh we have a lot of space in between as soon as it goes solid uh we get a lot of the strange overlaps that we had before we applied the alpha so when you make your alpha think make sure you keep some space between the leaves just to give it this fussiness because it helps hiding the fact that it's a billboard so just one quick note on the shading since it's picking up the shading of the object the really cool thing about this is that in order to change the overall style and look of this all we need to do is change the underlying material like ignoring the fact that it's doing this effect and just apply stuff like for instance smoothness let's add a bit of smoothness so i'm going to create a float holding down one clicking and i'm going to change this to be a property and let's just call this smoothness and plug it into smoothness and as soon as we crank up the smoothness you can see that we get this specular highlight on the model so already we're getting some sort of style going here we could also for instance add the fresnel effect so i'm going to add a fresnel node worth noting with the fresnel node is that it doesn't automatically output a black and white value so by default this will go really bright but i'm going to plug this into the emission just to show you what's going to happen and it goes super bright so the fresnel we need to make sure that it stays between 0 and 1. and we can do that by adding a saturated node so if you haven't used saturate this is a clamp node so it cuts off uh it's a clamp node but it's set to be only between zero and one so any value below zero will be zero any value above one will be one so it just cuts off the uh the low end and the high end so i'm going to saturate this didn't actually do that much i'm also going to multiply this by a color so just another multiply node and another color note holding down 5. and i'm going to set this to some different shade of green and plug this back in so this way we can quickly uh add a lot of style to our trees so already it's starting to look like something from a studio ghibli film or something we can also look at this thing the cool thing about this shader is that as long as the object is unwrapped the way it is we can grab basically any model with this setup so for instance if we have a model like this we could add our foliage shader to it and it automatically just becomes foliage there are two more things i want to quickly show you before i end this video so this effect the camera facing effect let's say we want to change the size of these so each of these quads actually let's change this to shaded wireframe so we can look at the quads like this so we know that each of these are the size of the uv they're like negative one and one so these are two in size if we would like to change the size of these all we need to do is to take this vector and multiply it by a single value and that will change the scale a bit so i'm going to add a multiply node at the end of this chain here so multiply and i'm going to set this to use a single value and again i'm going to make this a property and let's call this um billboard size and by default it should be set to whoops not the max the default it should be set to one just so if we don't change this in the material it will be the it will be an appropriate value so now if we click the material we can set the scale or the billboard size by just changing this value another quite cool thing that we can do with this is that same way that we're changing the size of these we can also change how close to the original surface they are because currently these are placed at the position of the original vertices but since all of the chords have their own normals we can use the normals in order to inflate the model in order to push the vertices away in the direction they're facing so let me just make a bit of space here we access the normals of the vertices by right clicking and typing vert and norm normal so vertex normal so this is a vector describing the normal of the word basic in this case it's pointing outwards from the face so if we take this value and we can multiply it to say how far we want to push the billboard away from the surface by adding a single value so changing this to again a property and let's call this inflate and multiply this value i'm going to let the default be zero because perhaps we don't want to use this all the time but so here we have the scaled normal if we add this to the billboard we're essentially just moving the billboard in the direction of the normal so i'm going to add a add node holding down a click to add an add node so adding this value here and plugging it in here and hit compile we now have an option to inflate the model so let's set the size back to one so it doesn't go crazy and now we can push the face push the billboards away from the faces in order to inflate the model we could also also push them inwards but you'll notice that the shading looks a bit messed up because the faces that are on the other side of the mesh getting in different lighting will push through to the other side essentially just inverting the mesh one thing that i would like to add that i think is really cool with this method is that since we are just using the uvs in this case to manipulate the vertices anything that we can do to regular uv coordinates we can do to manipulate the billboard itself so just to visualize this i'm going to change this to shader wireframe again and just zooming in here looking at these so for instance one thing that is very common to use when doing vfx manipulating the vert the uv coordinates is for instance using a rotator so let me just add one of those so a rotator so the rotator takes the uvs and given an anchor and the time the time in this case being the amount of rotation will rotate the uv around this pivot point by this much so in our case the original center of the uv cord is 0.5 and 0.5 but since we've already remapped those we know that in this case where the maximum is 1 and the minimum is negative 1 the pivot point will be at zero so i'm gonna plug this value as my uv leaving the anchor at zero and zero and just like this one suggests i'm going to add some time to this so right click and hit time and this is not how i would actually use it by just plugging time into it but i just want to show you what this will do so plugging time in and then plug it back into the chain here and hitting compile so rotating the uvs in this case doesn't mean rotating the texture inside of the quad it means actually rotating the billboard so in my example i'm using this effect to for my wind effect to get this jittering effect so that's essentially um using a rotator uh and instead of just plugging in time i'm plugging in the amount of rotation so i'm using a sine wave to basically wobble these quickly as the wind passes through um but i will not go through the wind setup in this one however if you would like to see it um i could perhaps do another tutorial if people would be interested to see how we could do a wind setup for this to conclude this video i would like to clarify that this technique is not a one-size-fits-all solution for making foliage it doesn't replace the traditional way of creating foliage where you make more branch-like cards and manually attach them to the tree trunk billboards are limited in the way that they're always facing the camera giving them an odd behavior when you're moving the camera around quickly they lend themselves better to more abstract art styles where the expression of the tree is more important than the accuracy and the overall level of detail i'm personally very excited for this technique though mainly because it requires so little manual setup once you have your shader the low complexity of this approach makes it very easy to experiment with your style especially when you can almost instantly go from a sculpt to a finished tree it's also very quick to experiment with the style of the leaves since it's just using a single circular alpha texture thank you so much for watching i hope you found this video helpful in some way i'm looking forward to see what others can do with this technique as i'm sure there are more use cases for it and let me know if anything is unclear and i can hopefully clarify it in the comments bye
Info
Channel: Pontus Karlsson
Views: 36,438
Rating: undefined out of 5
Keywords: tutorial, shader, trees, Unity, Amplify, billboards
Id: iASMFba7GeI
Channel Id: undefined
Length: 44min 16sec (2656 seconds)
Published: Tue Nov 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.