Procedural Content Generation UE 5.2 - In-Depth Overview & Building Forest Environment PART 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this tutorial I would like to show you how you can use the procedural content generation framework that was released with Unreal Engine 5.2 to create a forest environment in the first part we will learn about the basics of the PCG framework and explore various techniques for the creation of environments like density filtering spline sampling and mesh sampling in the second part we will then start in a new scene from scratch and build the procedural Forest environment that you're seeing here to start using the procedural content generation framework you need to activate it under plugins go to edit plugins and type procedural then take this checkbox here procedural content generation framework and you can also already activate the procedure content generation framework geometry script interop which we will be using later on for having access to the mesh sampler after taking these check boxes Unreal Engine will ask you to restart the engine so please go ahead and do so in order to use the procedural content generation framework in the scene we need to do two things we need a PCG volume and connect this PCG volume with a PCG graph asset so I'm just gonna delete this test setup here and build it from scratch I start with creating a PCG volume just type volume here then PCG volume pops up put it roughly in the same spot it's a bit bigger okay now that we have the PCG volume in our scene we need to assign it a PCG graph asset go to your content browser I have to follow you on the PCG tutorial right click type PCG and create a new PCG graph asset click the PCG volume in your scene and go to the PCG component under details and here you will see the slot for the PCG graph asset that you can just drag in here right now this input type is defined as actor what we actually need for this tutorial is to set it to landscape after doing so just double click the PCG graph asset and it will open up the empty PCG graph which just holds an input and output node so for this first PCG setup we are just going to create a surface sampler node right click and type surface sampler and then we're just gonna press select the surface sampler node and press d and also click generate on your PCG volume under PCG component so this is the base setup for the procedural content generation what you can see here is um points being sampled on the landscape so let's open up that graph and change some of these settings under points per square meter you can basically see the sampling density on the landscape so if we increase the points per square meter nothing happens yet because all of these settings here are depending on each other the point extends are right now 100 by 100 by 100 units so if we actually want to have a denser grid on the on the surface of this landscape we also need to decrease the points extends and as you can see now we are sampling more points on this landscape it's a random sampling so if we change the random seat you will see that the distribution of the point sampling changes on the landscape as you can see these points are currently oriented to the normals of the landscape that they are sampled on if we want to change the transform of these points we can add a node that's called transform points and then we can for example change the offset rotation and scale of the points currently the debug flag is still set on the surface sampler as we can see with this turquoise Point here on on the Node so if we want to actually debug our most current node which is the transform points we need to right click it press and check this debug checkbox or press d or even better press Ctrl alt d what this does is moving the debug flag from OneNote to another so as you can see at first we had the surface sampler being debugged and now we're moving the debug flag to the transform points we don't see any change yet because it's just like um being said on on the default settings right now so in order to see a change I'm just gonna apply some more Randomness to the rotation these values go from a minimum value to a maximum value and are distributed between these values randomly so all of these points are now being rotated on the on the z-axis between 0 and 360 degrees and we can also for example change the scale of the points and randomly scale them between let's say one and two and now you can see that we have a random distribution of randomly scaled points that are also being rotated between 0 and 360 degrees most of the time we don't just want to use the full set of points that are being sampled on the landscape but we want to filter them in some way sometimes based on the properties of the landscape or on other parameters I'm actually not going to create a new volume here because the process is exactly the same just make sure if you create a new one to set the input type to landscape in the PCG component settings so what we can see here is if I set the debug flag to the surface sampler we have a certain density of points and the point density is being set randomly by the surface sampling node a density of one is white and a density of zero is black and now what we can do is we can add a density filter node after this to filter out the points based on a certain lower bound and upper bound so in this case we would be only showing points with the density between 0.5 and 1. let's move on and actually spawn some static meshes on these points so first we're going to add a surface sampler put it into debug maybe set the point extends to 50 by 50. then apply some density filtering and after the density filter add a static mesh spawner in the static mesh spawner under mesh entries we can create a new entry unfolded and then drag one of our tree assets into this slot here now what we can see is that the trees are being spawned in the location of the points and also follow the orientation of the points let's actually turn off the debugging for a second so what you can see here is that especially on the slopes the orientation is really unnatural because trees tend to grow upwards so we might want to adjust this before the static mesh spawner I'm going to add a transform points node and I'm going to change the rotation to Absolute rotation and now you can see that all of the trees are pointing upwards to create a little variation I'm actually gonna change the rotation on the X and Y axis in a range from -5 to 5. now what you also might want to do is often offset the Z location of the trees so you don't see the open end of the mesh here just going to change the offset to -10 and then what you would do to create variation in your respond assets is to add further assets static meshes to the mesh entries array so I'm just gonna click the plus button here and add some additional tree assets now we can increase the density of the points maybe it also adjust the rotation a bit to make it a bit more diverse so this is a very basic setup for spawning static static meshes on the surface using surface sampler density filter and a static mesh spawner let's move on to the next topic which is Bounce and self pruning in the PCG framework the bounce Define how much space your sample points take up in the scene and you can then modify these bounds to fit the mesh that you are actually spawning and then use a node that's called self pruning to prevent intersections between the actual meshes so let's have a look at this node tree here I'm going to disable all these notes by selecting them and pressing e which stands for enable and just toggles enables disables the nodes which is a very handy shortcut and now what we can see is that the surface sampler spawns these points with a base unit um bound size of one but sometimes a bounce size of one is not enough for covering the actual extents of your spawn meshes so what we can do in this case is add a bounce modifier to change the extent of the spawn points and match them to your static meshes so let's enable the bounce modifier here and also the static mesh spawner and go in the bounce modifier and I just change changed everything from one to three so instead of one unit all of the points are now taking up the space in the scene of three unit on on all axes now what we can do with these changed bounds is add a self-pruning note after this just to show you the difference enabling and disabling it for example here we would have some intersection and with the self pruning it's gone so this is how you can use the bounce modifier and self pruning to fix static mesh intersections now let's move on to the next topic which is also touching the bounce modifier but focusing on fixing intersections between different kind of meshes as you can see in this setup here I have two kinds of meshes rocks and trees and there are no intersections between them and then there's also another type of mesh which is a just a test cylinder and if I move this cylinder in the scene here you can see that no trees are being spawned where the cylinder is currently located it's all happening dynamically so first of all we're starting with the surface sampler as usual I'm gonna set this in debug change the point extends maybe even smaller 25 and increase the density a bit and now I'm just gonna already add a static mesh spawner and gonna add my first asset here which is a tree then we're going to repeat the same process as in the other node graph so I'm gonna add a self pruning but it has to be before the static mesh spawner of course and also we want to we want to again change the point extends although it's it's fitting quite well it depends how um how dense you wanna want to put them of course if you would like to have some spacing between the trees you can modify the bounds or we can just keep it as default here because it seems to be working quite well so next we are gonna add some rocks for this I'm creating another surface sampler put it into debug turn off the trees for now and add an add another mesh spawner and in the mesh spawner under mesh entries I'm gonna drag a rock asset in this case I'm using one from quicksil Mega scans but you can use any kind of rock acid here and now if if we turn off the debug flag we see that the extents of the points here doesn't really fit the actual mesh so in order to change this we're going to add a bounce modifier in between set its debug flag and now try to adjust the bounds of the points to the actual mesh I'm going to try 0.6 on the x-axis 0.3 on y yeah that's pretty close already so maybe 0.65 on X and 0.35 on y that's close enough and that access is actually not important here right now so I'm going to leave it like um at one now if we want to change the overall scale of these points or of the of the rock assets we're gonna need to add another transform points in between I'm going to change the scale or I'm going to create a random scale between 1 and 3 here and by the way as you can see by default uniform scale is is ticked that means that it doesn't actually matter what you put in the y or Z slot here z-axis slots here on the scale Min and scale marks so only the x-axis slot will influence your the overall scale and um the other parameters will adjust based on this x parameter and I'm also going to change the rotation and randomize it a bit and then turn on the trees again and as you can see you have a lot of intersections between the rocks and the trees and now we're going to fix this by adding a difference node in between the self pruning and the static mesh spawner of the tree it's going to make some space here and add a difference node and change the density function parameter to binary then I'm going to drag from the output of the transform points to the second slot of the difference node and as you can see this fixes all the intersections between trees and rocks now you still might get self intersections of the Rocks because we didn't add any self pruning here's one for example if we change the um the seat of the mesh sampler that maybe we will find them in other positions or not at all right now that seems to fix it but of course if we want to make sure that the rocks are not self-intersecting then we can also add another self pruning node here for the rocks so right now that's enough for me and we move on to actually also excluding these um debug cylinders here in order to do this we need to add a certain kind of node that's called get actor data and to prepare this kind of technique you need to actually give these cylinder actors attack select them in the outliner search for tag and I call this tag PCG exclusion I'm gonna copy it also check that it's available on the on the other cylinder and then go back into the graph under get actor we actually select under active filter all World actors and then actor selection by tag and paste the tag here now what we need to also keep in mind is that we want to select multiple actors because we have multiple of these cylinders so make sure to tick this and then what we can do is we can just drag the output pin of this get actor on the same input slot of the difference node and the PCG network will add up all these different inputs and combine them to a combined exclusion or difference so this should already be working let's verify it by moving the the cylinder around and as we can see it's working so since we also already select the select multiple tick box here we can just duplicate the cylinder and it will automatically exclude all the cylinder instances in the scene now of course we could also do the same with the rocks and we would just copy this difference node here and put the output of the get actor data also here so as you can see now it's excluding both the Rocks as well as the trees from the cylinders in the scene you always want to make sure that you have some differences in your PCG graph so you're not spawning rocks into trees or other kind of foliage for now let's move on to another technique which is a slope filtering or density filtering based on slope it's a really simple graph we just have a surface sampler as usual and a particular node that's called normal to density in here we Define a normal that we want to compare the points against in this case it's just the upwards pointing normal and now it's taking basically the normal of the landscape comparing it against this normal that we Define here and setting the density based on this comparison and then we can apply a density filter to it and filter out the nodes that are fitting to to the normal that we Define in a certain um boundaries so with this for example we can filter out points that are just on the slope as you can see here or points that are just relatively level or even just the points that are on the edges of the slope just by changing the lower lower and upper bounds and for example this this last uh variant could be used to spawn Cliff assets um just on the on the downside of the slopes or on the on the edges basically it's a very handy technique so let's move on to spline sampling as you can see you can use a spline and Sample points along it and then spawn static meshes on the spline curve if you change the spline it's going to all adjust dynamically can add points to it and it's all going to adjust so I would like to set this up from scratch and show you how to do it in order to sample splines in the PCG graph you can add a spline component to the PCG volume actor so just select your actor click add type spline and add it here then open up the graph and now what we need to do is get a spline data node and keep the actor filter selected as self which is the default then after we're going to add a spline sampler node and put it in to debugging then go a bit closer here and add some points to the spline oops I actually duplicate the spline I just wanted to add some points here there you go and then we also need to click generate if you don't see anything yet all right this seemed to change something What's Happening Here is that the points are actually being displayed as stretched along the spline but strangely this doesn't actually seem to change the scale of the assets that are being spawned on it it just seems to be a display issue and I don't know if it's intended like this or if it will be fixed in future releases as the PCG framework is also still an experimental feature of Unreal Engine so I'm not exactly sure about it but it's definitely working and you can just ignore the um the stretched debugging view of the point extends here so all I'm going to do is just add a static mesh spawner add some mesh to it and there you have it then what we can do is to adjust the sampling of this spline is to actually subdivide it so subdivisions per fragment set it to five and as you could see here because the segments are closer together here you're actually going to get five subdivisions in this segment and also five subdivisions from this point to this point so depending on how uniformly your your points are just distributed on the spline you will also have a a density of sampled meshes accordingly if you would like to change this Behavior you can change the mode in the spline sampler from subdivision to distance and then adjust the distance increment according to your needs in this case it was set to 50 and based on the distance increment we are changing the density sampling density along the spline in the previous example we were spawning points on the spline itself and now we want to look into how we can spawn points on the inside of the spline or on the area defined by the spline so let's open up this graph the setup is almost completely the same we get the spline data with the actual filter self but then on the spline sampler we're going to change the dimension property from on spline to on interior let me actually debug this so as you can see this spawns a bunch of points on the interior of the spline and all I did then was apply a random density noise than a density filter to filter out some of the points and then just connect the static mesh spawner to spawn the tree assets now what's also worth noting is that you can define an additional density fall off by adding some keyframes to the interior density fault of property on the spline sampler so just add some keys here and Define the fall off now for now for example the density would go from full density on the outside of the spline to a lower density on the inside of the spline and we can use this later on to create some variation in our assets like scaling them accordingly or applying other changes to the meshes based on this density falloff now let's move on to some interesting use cases of spline sampling for example you can use blind sampling to automatically exclude water bodies from the foliage spawning and I would like to show you how to do this to follow along here you need to activate unreal engines experimental water plugin which you find under edit plugins just type water take this checkbox and restart the engine after restarting you can just edit a water Body by typing water and adding a river I already did this here so I'm just going to open up this graph and start building it from scratch so in order to get the spline of this River we're going to use the get actor data node and set the actor filter to all World actors and then change the actor selection from bitech to by class under class we're gonna just type water and select the water body River class also we can again check the select multiple if we have multiple water bodies that we would like to filter after this connect it to a spline sampler and put it into debugging again what we can see here is that the points are being stretched along the spline based on the subdivision of the spline sampler so what we want to do now is change the extents of these points to then use them as a difference on our foliage assets so I'm actually gonna create a transform points node set the debugging flag set the scale to Absolute and also increase the subdivisions per segment to maybe 20. and as you can see here now you have a lot of points along the spline they are very tiny because I just changed the scale to Absolute scale because now I want to change it manually to fit the width and depth of this River we also need to untick the uniform scale checkbox because we want to actually set all the scale properties individually so let's start with the x-axis I'm going to try a value of 500 here we actually need a bit more maybe 1000 here you can see the um the extents of the points and on the y-axis we're going to try 500 it's already a bit too much maybe depends 350 and then also increase the x-axis again maybe 1200 to cover the whole river and in this case we also need to set the z-axis and you will see why in a in a bit for now let's let's just add the surface sampler connected to the output of our input node and put it into debugging change the points extends slightly increase the density and add a static mesh sampler a static mesh spawner now we also need a difference node again set it to density function binary and now connect the output of your transform points node from the spline sample of the river to the difference node of the trees let's debug again the um the spline of the river here or the spline sample of the river so as you can see here kind of starting to work some of the trees are definitely getting excluded but not all of them and the reason is that the extents of this spline sampler points are not reaching the the bottom of the river so we actually also need to increase the scale on the z-axis to maybe 100 and now we can also see that we went a bit too far or we went a bit too too wide on I think it was the y-axis so let's decrease it to 250 yeah that should do it for now let's turn this off and let's change a bit the um the seat of the surface sampler maybe Also may make it a bit more a bit more dense and there you go your river is dynamically excluded from the foliage spawning now if I select the river water body River and if I change the points here say I want to add another point in between here and actually make it flow like this the PCG graph is adjusting accordingly all the PCG spawning is adjusting accordingly based on the rules you set in the graph and everything is working dynamically which I think is really nice it's a very similar setup for the lake so I'm just gonna go over it briefly the graph under guts blind data instead of selecting the water buddy River you're going to select the water body Lake then adding another spline sampler it's going to turn off the outputs here for now and debugging the spline sampler then what you can see is that these points actually appear on the surface or even below the lake um so I'm just transforming the points here and then using a node that we haven't used so far which is the projection node with the help of this node we can take the sampling points from our Lake and reproject them on a landscape and this is possible since in the PCG component under input type we still have landscape selected so we can just connect the input node to the projection Target and it will project the points on our landscape then let's enable our tree static mesh spawner increase the density of the trees here a bit by decreasing the points extends and now as you can see you have some flaws here in the in the difference of the points just because the point extends are are not really set up in a in an optimal way so let's actually increase the points extends here to fix this yeah that should do it and then of course also we can spawn some assets on some points of the lake procedurally but of course this is way too many so I'm just going to apply some density filtering first adding a density noise to apply it some random noise random density noise values to these points and then filter filtering them out based on these values that were being set by the noise then we can also further modify the points by adding a transform points node and again at some random rotation and scale Etc but we will go into more detail in all of this later when we built the actual Forest environment so this is just an example and I wanted to quickly show you next I would like to talk about Point grids with the help of Point grids you can create Assemblies of assets around other assets for example you can use it to spawn a bunch of rocks around these trees or foliage around other foliage or all sorts of of things that you can get creative with all right let's start by adding a surface sampler that will Define the points that we want to copy our points grid onto in this case I need less points so I'm going to increase the looseness of the points and now we're going to create the actual point grid we're not going to see anything for now first we need to change some settings we're also going to create a copy to points node and for the source pin we're going to set the output of the create points grid and for the Target pin we're going to set the output of the surface sampler what this node will do is copy all the points that we Define or that we create in our create points grid onto each of the points that we are creating on the surface sampler node but in order to see it we still need to change some settings on the create points node it needs to be set to local and also local inverse transform which I think just transforms the points of the point script into the coordinate space of the surface sampler let's set the debug flag and something is actually showing up here to make it more visible what's going on here we're going to change some of the settings I'm going to add a transform points node after the copy points set its debugging flag and set an absolute scale of five then I'm going to adjust the grid extents of the create points grid to something around 250. and actually I'm going to adjust the stands of the surface sampler points maybe 225 and then further increase the looseness and maybe change the seat also so now you can see that we are spawning these Point grids around our surface sampling points now we can add a static mesh spawner and actually add some static meshes to these points adjust the scale again because it doesn't really fit for this kind of mesh and then also apply some random rotation and some density noise and density filter now for the actual points of our surface sampler we're gonna add another static mesh sampler a static mesh spawner and add some other assets for example the tree now this is a very basic setup for spawning static meshes around other static meshes and we're going to go into more detail for this kind of setup later on when we built the actual Forest environment next I would like to look into volume sampling you cannot just use the PCG framework to spawn points on a landscape or sample points on a mesh you can also use it to generate points in a volume in 3D space for this we are going to create a volume sampler node and debug it right now it seems like the extents of our volume are completely filled with the one single point or at least we cannot make out the extents of individual points this is just because all of the points have a full density of one at the moment and are being displayed as fully white so in order to change this we're going to add some density noise on top of this and as you can see now you can see the individual points that are being sampled in the volume let's also add a density filter and increase the bounce here the lower bound and now as you can see you're randomly filtering points that are being spawned in this volume using the volume sampler density noise and density filter next I would like to talk about mesh sampling with mesh sampling you can sample points on your static meshes and use these points to spawn other meshes on top of these so we can create things like overgrowth or Mossy patches on rocks or as you can see here these kind of money plans that are growing on top of this rock acid to create this setup we're going to start with a note that is called create points we are using this node to create a single point in the middle of our PCG volume just click the plus button in the points to create array and leave everything at as the default value then also set it to local set the debug flag and you will see that in the middle of your volume you will have one single point we are now using this point to spawn a static mesh to the static mesh spawner I'm adding the static mesh of The Rock and I might also want to adjust the scale of the point so I'm adding a transform points node in between and now in order to sample points on this static mesh we need another node that is called mesh sampler drag the same asset in the static mesh slot here and if you if you look at the debugging now you will not see any points on the mesh yet and this is because the points that are sampled right now are actually being sampled in the origin of the scene so we need to bring these points to into the coordinate space of the single point that we created here for this we're using the copy points node and connecting the output of the mesh sampler to the source of the copy points and the output of the spawner to the Target if we set the debugging flag now we will see that we are sampling all these points on our static mesh we can change the sampling method right now it's set to one point per triangle but it can also be one point per vertex or a poisson sampling which we can then further Define here by setting a sampling radius to make it more dense or less dense and adjust the settings according to our needs I'm going to leave it at something like this right now and now I'm adding a static mesh spawner after the copy points node and I'm gonna add a foliage asset here just gonna drag it into the mesh sampling slot here okay now as we can see the foliage is spawned All Around The Rock asset which is probably not what we intended so we're gonna add a filtering node in between we're going to use again the normal to density and just use the standard upwards pointing normal add a density filter and then connect it again to the static mesh spawner now we might also want to adjust the scale of these points here and maybe something between 0.4 and 0.8 I also want to add some variation so I'm just also putting some other money planned assets here all right and there you go and this is a very simple example on how you can use the mesh sampler to spawn foliage acids on a rock acid procedurally the last technique that I would like to look into in the first part of this tutorial series is subgraphs with the subgraphs you can take certain functionality of your PCG graph and put it in a separate PCG graph then reference the separate PCG graph in your parent PCG graph to create additional functionality or to Outsource complicated part of your graph and make it more structured for example we can take this mesh sampling graph here and reference it in another PCG graph that is sampling points on the surface to create this kind of setup we're going to start with the surface sampler node to define the points that we then want to copy our mesh sampling graph onto I'm going to increase the looseness here because we don't need so many points and then I'm going to drag into this parent graph the actual graph of the mesh sampling and connecting the nodes right now you won't see much yet because there's still some changes that needs to be done to the mesh sampling graph so let's jump into this graph and for now I would just like to disconnect the create points from the transform points and I would also suggest you to click the cleanup button in the PCG mesh sampling volume to completely stop the generation of procedural assets the reason for this is that we are now changing the way we are sampling points on this volume in order to prepare it for being used as a subgraph and it would completely overload this volume with points which leads to crashing after you press cleanup you can then just connect these two nodes the input to the transform points and you should see your mesh sampling subgraph being duplicated on all the points that we are sampling on the parent graph and this concludes the first part of this tutorial and overview of the PCG framework in the next part we are starting in the new scene from scratch and building a forest environment using all these various techniques that we learned in this first part
Info
Channel: ExitSimulation
Views: 39,069
Rating: undefined out of 5
Keywords: Unreal Engine, Procedural, World Building, Environment, PCG Framework, Procedural Content Generation, Spline Sampling, Mesh Sampling
Id: BJZc06F7ci0
Channel Id: undefined
Length: 50min 37sec (3037 seconds)
Published: Wed Jul 05 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.