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