Hi everybody! It’s Oskar Świerad here. In this video I’m going to show you how you can add a decent amount of randomization to a highly modular building. What you can see here is a building that has
a varying amount of damage between floors, random color pallettes for items and even certain items are hidden
on some floors, while visible on the others, like the air conditioners. On the bottom, we have a layer of dirt which is not visible on the upper floors. The entire building is made of this single module being copied with Blueprint completely automatically. Here I only specify the number of floors
and the number of segements and all the randomization is done within one material. There is only one material used for the entire building except for the windows. So everything happens
within this single material. Let me show you an additional feature of this shader which is choosing the color of the paint both secondary paint and the primary paint color and as you can see, the damage
isn’t affected by these changes. So how is it all done? The first trick is how I made the base color texture. It has a transparent background
and there are 2 sets of textures. So the first one is clean
and the second one is damaged. The clean… …and the damaged texture. And the additional thing I needed here
is the vertex color Basically, my vertex color is used
for masking certain features. The red vertex color channel gives me the mask between
the primary and the secondary color of the background. The green channel was used for randomizing
the color of the secondary items. So as you can see, here we have a yellow cloth while here here we have a teal cloth. And the blue vertex color channel is used for randomizing – or rather –
for adjusting the offset in the X axis. So the darker the color, the less
the object will move on the X axis. It’s controlled by this parameter in the shader. And there is another thing that was
very important for this shader. It is the random number that is generated, or: caluclated,
for every segment in each floor. For each individual mesh. And this single random number that I generate
allows me to randomize all these features so they’re not identical from floor to floor. Even the hiding threshold is varied, as you can see. It’s not only a threshold on the blue channels.
It’s also the additional random number mixed in. So before I go into the details in the shader and the blueprint, let me show you can easily create
the vertex color in the software called Houdini. You may be interested in Houdini, because lately
there was a great Unreal Engine stream about it with the staff from SideFX, the creators of the software. Houdini is basically a full 3D creation suite.
It’s a full package but it’s workflow is entirely node-based. Every operation is a node. But it’s really an artist’s tool. I will do an entire big tutorial, a course on Houdini, next month But now let me show you how you can
create the vertex color in this, for our needs. First I begin with the Color node, set “Primitives” here and the “Color” to black. Okay Now I want the red color only on the walls. As you can see the number of the polygons here
is quite big for a manual selection. So instead, I enable “Group Selection” and I will select by UV islands Here all the islands are designated for me.
I choose this one and this one and the middle one Okay, great. Now my vertex color is bleeding to the another wall
because they are connected, the vertices… so I can change the class to “Primitive”
and it’s perfectly sharp. Now, for the green channel I take a node that’s called “Attribute Randomize”. There’s really a ton of nodes like that. Houdini is an artist’s tool. You can write scripts, you can write code –
and you will, in the advanced later stages but nodes are really useful. So here “Primitives” again. And as you can see, it shows a
random color for every primitive. It’s not exactly what we want. The first thing… is that we want only to modify
the color of secondary items. Okay, great. Only these things are randomized Now I want it to choose a random value
for the entire submesh. But this object is only a single mesh.
It’s not separated into objects here. I merged it all to export it to Unreal. It’s completely not a problem for Houdini.
I just need a “Connectivity” SOP. “SOP” is a name for “node”. Now, “Attribute Class”. Basically, everything
[vertex/polygon data] in Houdini is an attribute. So here you can see the attribute for position
that is written into points and this is the attribute for each
primitive, that is: each polygon. We can rename it to ‘submesh’. And here we have an attribute that was created by us.
It’s not a fixed set of attributes like in other software. So here we go to “Options”, choose a “Seed Attribute”: ‘submesh’ and we have random values! Now, we don’t want it to override the red channel and only select the green channel. So what I will do is to write the “Max Value” of red: 0, blue: 0.
Blue remains 0 to 1. Instead of “Set Value”, I’ll choose “Add Value”.r I want to repeat the same functionality
for the blue channel but on a different selection of objects.
I want only this thing to move Now it’s randomly choosing values between 0 and 1. Maybe it should be between 0.1 and 0.5. Perfect. As you can see, instead of replacing
the values, it’s adding the values. And that’s it! We are done. Now let’s go back to Unreal and I will
show you the Blueprint part of this. So basically, how to create an object like that. with the control of number of floors
and number of segments. First we need to go to the Content Browser
and create a new Blueprint. The “Actor” type will be OK. It’s the basic type of blueprint Then you have to drag it onto the level. Basically, a blueprint is a template of the object. So we can create many instances of a single blueprint.
This is the one I created and we edit it here with the shortcut Ctrl + E. “Blueprint” is both the name of
the basic type of object in Unreal but it’s also the name of the visual scripting language that the behavior of the object is driven by. And there is a special kind of graph
in every object, called “Construction Script” The execution flow starts here. And if start to type “Static Mesh”, the I have a
suggestion to “Add Static Mesh Component” That’s what I want to do. It basically adds a Static Mesh into this object.
Because an object can consist of multiple meshes. And that’s what we need. And as you can see, this is our object.
Here I can specify “Relative Transformation” by “Make Transform” that is suggested here, below. But I don’t want to manually add every mesh. I want it done by a loop – an automatic loop. Here on the left, in the “My Blueprint” panel,
you can add your own custom variables. So my first variable will be ‘NumberOfFloors’. On the right, in the “Details” tab, we change the type
to “Integer” – which means a whole number and make it “Editable”. Then it will show up in the viewport also, not only here. So basically, the user can edit this value. And for my convenience, I will create
a variable of type “Static Mesh” for example: my wall module. Now, when I have these two variables,
I make a “For” loop. First index will be ‘0’ then the “Last Index” will be the number of floors – “Get”, now type in “minus” symbol “Integer minus integer”: minus one. So the first module will be numbered as 0,
the last one will be number of floors minus 1 Okay, and for each floor, I want to create
a specific amount of segments. In the “Loop Body”, which is what happens
in every iteration of the loop, I create another loop. ‘NumberOfSegments’ minus one. And in the loop body I add a Static Mesh component. Let’s make some transformation for it And what I need to do – what’s very important
and you can miss it easily, is that this node, in its “Details” tab,
has a “Mobility” setting here. By default it’s “Movable”. It is a building, that I want to light with
static lighting – GI and so on so I set this to “Static”. There is a lot of other options too, typical for
Static Meshes. They are all OK by default for me. Now what should be the transformation
of every module? Basically, the number of the current floor
multiplied by the height of the module will give us the location on the vertical axis, while the number of the current segment
times the width of the current module will give us the X axis location. So, fortunately, here we have the index
of the current iteration of the loop: 0, 1, 2… and so on. I will multiply it by a float number. Now I drag my mesh here,
basically reading this variable, and I can get its bounds. Now what I have here is a complete object
that contains the boundaries of the object. But I can break it and then I got “Box Extents”. Extents here mean the half of the width,
height and so on. So it’s a half of each dimension of the object. So I can break it further, into X, Y, Z. Now to make the location, I can click
“Split Struct Pin” here I have location X, Y, Z. I take it and it will be my Z location. Something doesn’t work and I have to check why… Okay! What I forgot is to set the template
that will be used to create the Static Mesh. So I take the newly created Static Mesh,
set “Static Mesh” here, and here I take my variable. And it works fine. Here I specify the number of segments here we can change the number of floors… When we go back to the viewport,
we can still access the values here, in the “Details” tab. So the number of floors and the number of segments. And that’s basically how I created this one. Let’s see the inner workings of the shader.
So this is our material… Here, I mix two sets of textures
and set the underlying color which is the color of paint. The damage is mixed in using a cell noise that I painted myself in a 2D software. I packed 2 noises into a single texture, to save
on space and video RAM (video memory). When you are doing such packing – and basically
for all kinds of masks, like roughness, albedo [?!! – not true!] you have to set the “Compression Settings” to “Masks”. The same packing is applied to metalness, roughness
and occlusion, which all are packed into a single texture. Red is metalness, green is roughness
and blue is occlusion. In the DXT compression, the green channel has more information
– more bits – than red or blue channel. So basically, green channel preserves
more details than the other channels. And when you can avoid alpha, like I do here,
then the size of the resulting image is really, really lower because it then can use a different compression
technique that doesn’t require alpha. So it’s much lower than just the 25% that
intuitively the [lack of] alpha should save. so I recommend using the textures of 3 channels,
with no transparency unless you need it. As I said before, my base color has the alpha channel,
so I can use any color as the background and have the damage being drawn on top of it. Here is the mixing of the textures – so “Linear Interpolate” node the shortcut is L and click. Or right click and
“Lerp” – “Linear Interpolate”. It mixes between two textures, or: two colors,
with the “Alpha” being used as the factor of the mixing. It’s called “Alpha” but it’s just a factor,
a scalar number. And what’s returned from this white pin in the
texture node is a vector of three. It doesn’t contain the alpha – which is given here,
as a separate value. So first I have to mix between base colors
and then I have to mix between alphas. Later, I will mix between these
colors and the final texture using the alpha channel as the factor
for the linear interpolation. It’s how you do mixing textures on top
of each other with transparency. You use the transparency as the alpha
for linear interpolation. So this is the background and the mix of these two base colors, here,
is the foreground – with alpha being the factor. Then after I mix the combined metalness,
roughness and occlusion, I can split it into separate channels. Before I’m finished with this,
I apply some dirt to base color. To create the mask that is used
to apply this dirt I create a linear gradient from
the lower part of the building up to a certain, specified height. So here I have height minimum, height maximum and this – this is my own Material Function.
It’s a “Remap” node. Basically, it’s used like that: It takes a value: Z value of the
world position of the vertex which is the height of the vertex and it takes the range
that the value is within. And what I want to have as a result is the same value being fit
between the range of 0 and 1. So I’ll really have a gradient
which I can use later for mixing. It’s also called normalization
and it works like that. So it’s a really simple function. Really easy to calculate, not a heavy function
and it’s extremely useful, everywhere where you have to deal with distances, different ranges Even adding contrast with this simple function. Then I use the quite new function in Unreal,
which is called “Noise”, to add some detail to the
basic linear gradient. You give a vector of 3, called here a “Position”, and it can really be a position, multiplied by some
value of frequency of the resulting noise. It’s like the scale of the noise –
the multiplication of the position. And what you get in return is a value,
for example between -1 and 1 or it can be between 0 and 1, or whatever. a random value – but not completely random.
Not a white noise. Instead, you can here choose the function
that is used to compute the noise and the noises are unfortunately very heavy.
They add tons of instructions to the shader. So please make sure to choose the noise that is
most lightweight and still OK for your needs. In my case it’s the “Fast Gradient”. It’s really the most simple –
most ugly, OK – but most simple function of noise to choose. So “Fast Gradient” is enough. Now, the “Levels” also affect performance.
So for example, if 2 is OK, choose 2. Only then, look how it looks like and add more. That’s where I get the mask. I take it to the power of two
to add some additional darkness and contrast and again use linear interpolation for that. Now let’s see this part of the shader. This is a very useful thing
I told about some time before It’s again a noise function, but this time not taken
from the vertex position, but from the object position. So I want to have is a random number
between 0 and 1 for every separate object. If you were doing instancing instead of Static Meshes, then you have the access to the node
that’s called “PerInstanceRandom”. And you can use this “PerInstanceRandom”
instead of the “Noise” here. It’s automatically generated
for every separate instance allowing for some nice randomization of them. I created this material in such fashion
that you perfectly can use instancing with it. So instead of Static Meshes, we can use instancing,
like Hierarchical Instanced Static Meshes which I made a video about before. And then you’ll have huge savings in terms of performance. It really saves a lot of video RAM,
a lot of runtime performance but then you won’t be able to use static lighting [with LODs].
Only dynamic lighting will be possible. So really it’s up to you. If you can deal with not having static lighting, then
instancing is a way to go here, in a project like that. Now what do I use this for? I modulate the green and the blue vertex
channel color by this random number here, by adding it and here, by multiplying it. What I have here is picking a
random color for each item. So I take this value from the vertex color
and this per-object random value and use it as the U channel in my
UVs for this texture. So basically, the horizontal axis by this value,
while the vertical axis is set explicitly to half. And the “ColorPaletteTiling” is like a frequency of this palette. So we have more randomization within
the vertex color’s 0-1 range. By default I will set it to 3. What I do here is creating a mask
for this change of the color. Because I only want to the change the color of the items,
not the walls, dryers, windows and so on So if the value – it’s again a “Remap” function – if the value is lower than 0.01, it will be black, while when it’s higher than 0.015,
it will be white. Kind of a threshold for it. And then I use linear interpolation
to mix in the resulting color from the palette. Here I hide certain items. So I take the blue from the vertex color and here it’s the same feature like above –
the masking feature, but done differently to show you the possibilities. I subtract 0.01 from the vertex color. So basically, values that are 0.01 or lower
than this – really small values, will end up being below zero – or zero,
while everything higher will remain above zero. So by subtracting this small number and then
by using the “Ceil” function, the ceiling, I round the value to the nearest higher integer. So the “Ceiling”, when it encounters someting below zero,
will return zero – black
I round the value to the nearest higher integer. So the “Ceiling”, when it encounters someting below zero,
will return zero – black while in another case it will return one,
so – full white. Then I multiply what I got by the blue vertex color
plus this random number from the object position. And by doing this I receive the final value which I use
to control whether I should show or hide this object. Here I have a “HidingThreshold” parameter.
If the new value is above the threshold, I choose to hide the item. It will be zero in the Opacity Mask. And… Otherwise, I’ll decide to keep the item,
so 1 in the Opacity Mask. And the “Blend Mode” of the material is set to “Masked”.
It’s like [binary] translucent, without the heaviness of translucency. It only allows for having 0 or 1, as I explained
in my tutorial about translucency in Unreal Engine. So “Masked” is very lightweight. It’s almost
the cost of a regular, solid mesh and then I output either 0 or 1
to the Opacity Mask, here. Now the final feature is moving the items
in the X axis, randomly. So again, I take the blue channel of the
vertex color, I take this random number and first thing I want to do is to take the number,
which is between 0 and 1 and make it between -0.5 and 0.5. So scaling it – multiplying it – will always
be done from the center, or: zero. Then I multiply it, just for convenience, by 100
and then multiply it by the “PositionOffsetStrength”. Now it’s only the value on the X axis –
while we need the full vector of three to move the final position offset. So the “Append” node will first take
a scalar number – a single number, and add a 0 to it as a second component. The “Append” node adds another component
to the value, making it a vector of two and from a vector of two
making a vector of three. Here I take a “LocalPosition” of the vertex. As you can see, it’s a simple function. It’s up to you whether to use it [laughter].
It’s quite simple. And I add this offset to this local position. Now, what we have to finally give to the engine
is, unfortunately, a world position offset. So it’s an offset in world coordinates,
not local coordinates. It’s not even the final value.
It’s just an offset. So how do we convert it? I first add this offset to my local position, having [getting] a local position that is moved, then I transform this moved
local position into world space and I subtract the original
world position of the vertex from this new world position of the vertex –
basically having a world offset in return. Then I provide it to this “WorldPositionOffset”
and that’s it. So this is our entire shader and, as always, you can download it from my Gumroad page. There is the whole project, containing
all of the tutorials made so far. Of course, should you have any questions regarding
this project, please ask in the comments and if you have time and possibility, if you
know the answer, then help the others. I hope this thing was useful to you, I tried to show
a lot of features, contained in a single project. And I have to say that I’m sure that
you’ll make a lot better material out of it, taking my project just as a start. It was a very nice surprise, when ZioYuri78 took my tutorial and created
his own optimization of it. So basically what I said was impossible, now was
proved to be perfectly possible in Unreal. So yeah, thank you very much for watching good luck with your own projects
and using it in your own stuff and see you next time! Cheers.