[MUSIC PLAYING] SPEAKER 1: Listen, my fortune. MR MURRAY: What do we have, Captain? CAPTAIN: We have land, Mr. Murray. [MUSIC PLAYING] SPEAKER 2: Hey, everyone. The latest Unreal Fellowship
Workshop is a wrap. And the Fellows' projects are
ready to make their debut. Showcasing their exploration
of real-time production design and worldbuilding from
dimly lit sci-fi labs to battle-torn ruins
filled with dire warnings, the variety of environments these
artists created is phenomenal. If you'd like to get a
heads-up for applications, subscribe to our newsletter. And while you wait, watch
the inspiring Sizzle and get started yourself
with loads of courses on the Epic Developer community. Unreal Fest is heading down
under for the first time ever. In the region, join
us on the Gold Coast from June 21 to 22 for two
action-packed days of skills development, Epic dev support,
networking, and an Unreal Fest party. Get your ticket for Unreal
Fest Gold Coast today. Filmmaker Tim Richardson's
short, Neon Rapture, takes Iris Van Herpen's
futuristic fashion line into a stunning
virtual world, blurring the line between couture and cinema. By digitizing the experience,
collections take on new meanings, making even casual viewers rethink
how far a piece or an idea can go. In our latest spotlight, see how
they brought their collection beyond the catwalk. [MUSIC PLAYING] Now to highlight a few top
tutorials from this month, take a swim with community hero,
Death Ray CG's ocean simulation tutorial, which is a step-by-step
guide creating a beautiful ocean system entirely with Niagara. When you're ready
to step back inside, see that USD demonstrates the process
of creating a floor plan in UE path tracing. It's easy to set up. And the result looks lovely. Plans like these can be a very useful
addition for archivist projects. Authorized Unreal Engine
instructor, Gabriel Paiva, takes on the commonly misunderstood
camera look at tracking attribute and will help you leverage
its uses like a pro. Dig into these tutorials and more
in the Epic Developer community. Bouncing to this week's
community spotlights, prepare for hordes of angry
buttons in Scotland-based Reality Adrift Studios, Button Pop. Defend yourself with a variety
of turrets and generators, collecting riches along the way. Wishlist Button Pop on Steep. Looking for a retreat in the woods? CG artist Ilya Luongo built a
home inspired by Robert Hutchison Architecture, featuring various
lighting scenarios created in UE5. Check out lights in the forest
and more of their incredible work on their ArtStation page. And we'll leave you with
this gorgeous demo reel from animation director
and artist, Alireza Fatehi. Battle against raging monsters,
race through fantastical futuristic cities, and beyond, in
their exciting showcase. Watch now and show them your
support in the community. Thanks for watching this week's
news and community spotlight. TINA WISDOM: [LAUGHS]
Hello, everyone. Welcome to Inside Unreal, a
weekly show where we learn, explore, and celebrate
everything Unreal. I'm your host, Tina. And today with me I have
two incredible guests who are going to be going
over the material UI labs that we have set up today. The link for it is currently
pinned in the chat. So if you haven't yet, go
ahead and take a second to go grab that project. It is free. And you can go ahead and
follow along with what we're going to be going through today. But before we dive in, I do
want to quickly introduce our guests for today. So first up, we have Irene. Would you like to tell us just
a little bit about yourself? IRENE ZANON: Hey. Hi, Tina, thank you for having me. Yes, I'm Irene Zanon. I'm a senior technical UI designer
on Fortnite at Epic Games. I have been a technical UI
artist and technical artist. In the past, I've worked-- before Epic I worked at Ubisoft. And before that, I
worked at an indie studio in my home country, which is Italy. And I'm really excited to be here. I'm really excited to talk
to you about the material up. TINA WISDOM: Awesome. Well, thank you so much
for being here today. Very excited to have you and dig into
what you've brought in here today. And then, second up, but certainly
not last or least, we have Pavlo. Would you like to tell us a
little bit about yourself as well? PAVLO GRUBYI: Good day, everybody. My name is Pavlo Grubyi. I am a technical UI design
director on Fortnite at Epic Games. Been here for almost two years. Originally, I am from Ukraine
and I have been in the industry for over 12 years. And here I am trying to deliver
the best tools and practices I can, together with the awesome teams
of the Fortnite and Unreal Engine to deliver the best tools
and practices to make sure that we have our production
topnotch and to the high standards. That's me. TINA WISDOM: Awesome. Well, thank you also for being here. I'm very excited to get
into the project today. UI, I know I was talking a little
bit earlier before the stream, we even started about this. But UI is definitely a topic
that I feel like we don't get to touch on enough, honestly. I don't know if there
will ever be enough because it is such a vast topic with
so much available to be done in it. So I really appreciate
you being here and also providing this incredible
project for anyone who might be interested
in getting started at it and wasn't sure where to go. And now they just have
this beautiful present that you have made, and packaged,
and tied with a nice cute little bow just for them. So thank you so much for being here. IRENE ZANON: Very excited. Very excited. We worked hard on this. And we are really happy that finally
people can [INAUDIBLE] the project. And as UI people,
as you said, there's not a lot of UI
educational material there. Many of us are self-taught,
especially when it comes to material. And so, we just wish
to bring something that can help people started,
especially if they come from different backgrounds, for
more different types of software, like Photoshop, or Figma,
or Illustrator, and so on. So Pavlo is with me today
because I needed some support. And he will also be
helping me with the Q&A. But I have a presentation for you. And then I will have also a demo
so I can show you in the Engine how you can use the UI material lab. And I can share my screen now. So, we did introductions already. I feel like I also need
to introduce my cat also, just because you probably will
see him a lot in the project and also probably
during the presentation. So I mentioned having
worked at different studios. So as a senior technical designer,
I work with materials quite a lot. I am mainly self-taught,
like as you most of us are. And my background before game
development was graphic design. So I was used to
certain type of software that works in a certain
way that is not necessarily how UI materials work. And that's one of the reasons
behind the material lab. So I noticed some stuff
while working with materials. First thing, not going to lie,
materials are intimidating. They introduce new concepts
that we might not necessarily be used to, like the concept of
UVs. They rely heavily on math. And many nodes' names are
just not self-explanatory. Now I know that Lerp stands
for linear interpolation. But if someone just wrote Lerp
somewhere, I just didn't know. I wouldn't know what they meant. And I always wondered
[LAUGHS] does saturate have anything to do with saturation? Well, the answer is no. Also, if you come from
certain types of software, you are used to expressing
your values in pixels. And you can't really do
that in UI materials. Most of the values that you will
be using are zero to one values. So it just works differently. So, yes, I do use materials a lot. But most of the time, I'm
just reusing the same nodes over and over. I find myself having to loop time. So I will take the game
time and I will multiply it by a speed parameter, and
then I use the Frac node, or I have to do some
basic transforms, like translating, rotating, scaling. I need some gradients, like linear
gradients, or radial gradients. But it's always the same
combinations of nodes. And despite reusing
these things very often, I still don't always get
it right the first time. Math is hard. And this is a fact, especially
when you try to translate math into something visual. It's not an immediate translation. And you have to keep in mind
the sequence of operations, and even the order of
inputs in some cases. So for this stream, I want to assume
that people who are watching this are already familiar with
the very basics of material. So we'll not be teaching
you how to create a material or how to create a material instance,
although you will see me do that. So if you don't know have to do that,
you will just see how it is done. But I would still like to
cover just a couple of concepts that I feel are important to explain
so that we're all on the same page and pertain particularly
UI materials so that we all know we're all on the same page. So we know that materials are
basically sets of instructions. And these instructions determine
the appearance of the pixel-- of each pixel-- of the
object we want to render. So what do we want to render? If you're not used
with UI material, you might think that you're
rendering a mesh, because that's what most materials are doing. They're rendering pixels on a mesh. But in the case of UI materials,
we are rendering widgets. So we are rendering
images, borders, text. They are just different
types of objects. What makes a material
a UI material is that we use the user
interface material domain, which is what you
can set when you create or when you have a material open. And what this does, it changes the
output of the material to three or four values that we can set. And these values determine
what the pixel looks like. So the values that we can set
are the color of the pixel. So it's an RGP value. And the opacity of the pixel,
depending on the blend mode. If it's not opaque, you
can decide the opacity. And this is the alpha. And this is zero to one value. And we can also control
the screen position, although we will not cover
this during this livestream. And, yeah, as I mentioned, we use
zero to one values for almost all of them except for
the screen position. So things to keep in mind. Each pixel doesn't know
anything about the other pixels because pixels are all
rendered at the same time, pretty much, all of them. And so, they don't
know about each other. And each pixel doesn't know what
it look like in the previous frame. We don't store information
between frames with UI materials. So what does the pixel
know, and how does a pixel know what it has to look like? A bunch of things. The most important
stuff is the position of this pixel relative
to its container. And it's what we call
the UV coordinates. So UV coordinates is
a couple of values. The first value is the
horizontal position of the pixel. So all the way to the
left will be zero. And all the way to
the right will be one. And all the values in between. And the second value is
the vertical position. So all the way to the top it will be
zero, and all the way to the bottom it will be one. This position could be relative
to the container as fit, but, also, it could be a relative
to something else, for example, relative to the screen. These are called different
types of coordinate spaces. A material function
that is in the Engine and that we're using
Fortnite all the time, but I feel like it's a bit obscure. I don't find much information
out there about this, but it's really vital for UI
materials, is the get user interface UV. This not only outputs
different sets of UV coordinates but also
the pixel size, which is the size in pixels of the container. And this is important because
you might, as we said, we have zero to one values. So where zero and one are the
limits of the container where we draw something. This means that if you
stretch a container and you don't account for that,
the content will be stretched. But if you know how big the container
is, you can compensate the stretch. And that's what the pixel
size node is useful for. And there's another information
that the pixelize is the game time. And this is very
useful for animation. We use animations inside
materials a lot in Fortnite because it's just
more performant for us to animate more in materials
rather than a Sequencer because it relies more on
the GPU rather than the CPU. A concept that I think everyone
is familiar with but still better to make it clear because it is
the foundation of the material lab is the concept of material functions. As I mentioned, if you find yourself
repeating the same operations over and over, it might be
worth just packing them into a material function,
which becomes an asset that you can reuse in different materials. So you don't have to
redo the same operation. You just drag a material function,
and it does the thing for you. It contains the logic. It has inputs and outputs. And if you are more
familiar with After Effects, I think it is a similar concept
to the concept of effects in After Effect. It's not the exact same
thing, but the concept is similar, where there are
some bunch of operations that happen under the hood. And what we see and
what we can control is a bunch of input
parameters, which are the same as the inputs in
our material functions. And, basically, these
parameters just change the output of our material function. And one difference is
probably that we can have different outputs with Unreal. So, for example, we can have-- if we
have a function that draws a circle, we can have an output that draws
the discus or the field circle and the different outputs that
maybe draws only the outline. But for the rest, they
work in a similar way. And of course, it wouldn't be
UI if we didn't mention UMG, because UMG is the UI editor
that we use in Unreal. Materials integrate
perfectly into UMG because all the parameters
that we create in our materials can be animated. They can be animated into
the Animation Sequencer. But they can also be set
directly in the Blueprint. And just a quick side note. Something that we
try to do in Fortnite is to animate less parameters
in Sequencer for the reasons that I said before, because we
want to move our calculations from the CPU to the GPU. And so, for simple
transitions, like you have a button that has maybe
a hovered and unhovered state. What you would do is you
would have a control that is the hovered, which is just a
float that goes from zero to one. And that's the one that you
animate in the Sequencer. So you want to make just one
parameter in the Sequencer. And inside the material,
you have parameters depending on this control. So, for example. In this GIF, we have a color
for the button when it's hovered and the color for the button default.
And we animate the hovered control. And what happens inside the material
is that it picks one or the other, depending on if the
button is hovered or not. And so, yeah, this is something
that can help with performance of the game and also can
help preview the states, because you can preview
the hover state directly from the material instance. So time to talk about
the material lab because we haven't
even mentioned it yet. So the material lab is a collection
of material functions, not only material functions, but
also techniques or something that we call techniques, which is
either combinations of material functions or best practices,
like the use of SDFs, which we will talk about later on. The philosophy behind
it is that these are intuitive to use,
especially for artists. And we will see later how
we try to make these happen. But the idea is that they
can be very easily chainable and can be used like building blocks. So you can chain a translator,
rotate, and then a box, and then you can slant it, and then
you can turn it into half tone-- I don't know. What the material
lab is not, it's not an explanation of the super
basic stuff, as I mentioned. So it will not be explaining
to you what a step is. But, also, it is also
not the extreme opposite. It's not this complex
material breakdown. It's in the middle. And the material functions
that you will find in a project tend to be quite generic,
not super specific, because we just don't
feel that there's much use for material functions
that you probably would use just once in your life or never. So nothing too specific. This is an overview of the material
functions that we have in the lab. So when you open the
project, you will see that they are in the form of cards. And these cards are
all different examples. And we have different-- we sorted
them into different categories. And the last tab, which
is the Applications tab, has a collection of widgets. So you not only you will
be able to check out how the materials are
made but, also, you can use them in UMG in real cases. So to make a button, or to make an
inventory slot, or a progress bar, or whatever. So you can really check out how
maybe parameters can be animated, and how you can trigger an animation
for a button that maybe gets hovered, or stuff like that. So the main purpose of the
material lab is educational. These materials that
we have in our examples are heavily commented,
so that if you really want to understand
what's going on, you just open the material or
the material function, and you just read all the
comments and follow through. And, hopefully, it is
easily understandable. But, also, at the same time,
for people who are starting-- and not only-- we want to also convey some best
practices that they can use. And we will see later when we
talk about SDFs in particular how you can really boost
the performance of your game by using less textures. And also, the visual quality of it. And you can get better animations. There's just lots of advantages. But, also, if you are already
working with materials, you might just want to
expand your material library. And that's also, we
hope, a useful tool for that, because there are
a lot of material functions. Maybe you just want to check out
if there's a different way of doing something that you're already doing. And why not inspiration? Because maybe you just
started with Unreal Engine. You don't even know
what you can do with UI. And maybe you don't know you can do
certain animations inside materials and stuff. So we hope this can
provide some inspiration. And maybe you are a
designer or an artist and you just want to
prototype something. This is really a safe
space to do that. It's called material lab for
a reason because it really is meant to be experimented
with and to be just played with. So I just want to give
you a little tease of how these cards that
we saw before would translate into material functions
in a practical application. This is not the demo. I will just do a demo
just in a little bit. So I will not really explain
exactly what's going on but just give you an idea of how
you would go, for example, creating this objective marker. So you could maybe use this for
a capture point or something. It has this diamond that-- and that's a progress
bar, that fields. So the way you would go with
that is, if you didn't even know where to start, you
would probably just check all the other functions
that we have in the examples and just try to find something
that is good for you. So first, I would think,
yeah, I would just take a box, and I will rotate it 45 degrees. And I will take the
outline of the box. And then I will use some sort of
mask to mask the progress the way I want it. And that's how we go with it. So the box, we have
a material function. It's the SDF box. And as you can see, you have
a bunch of input parameters. And we take the outline output. And this is what it looks like,
just an outline box outline. So now we want to rotate
it 45 degrees and also to scale it to fill the container. So this is the customer
data that is in the Engine. And this is our scale function. So see, we are
chaining them together. And this is what we see now. Now we basically want to be able
to find some gradient that we can use to mask the progress. And this is what the
square gradient is for. It is a gradient that goes from
zero to one along a square. Now I'm just here storing the
UV so that I can use them-- that I can give the rotated
UVs to the square gradient. And this is what it looks like. And I combine it with
a step so that it becomes a harsh mask of zero or one. And I'm using linear time,
in this case, to animate it. But, of course, this could
be set by a parameter maybe that you set in Blueprint. So this is our progress mask. So now, we want to take
the outline that we had. and we want to intersect
it with the mask. So the mask will mask the outline. And we use the min node for that. So this is the outline
that we were using before. This is the progress
mask that we made. And this is the output. It's a masked outline. And now we just make another box
for the thinner background line. And really nothing fancy about that. It's the same box just with
slightly different parameters. The stroke is thinner. And it's just a bit smaller. And this is our progress background. And we just combine the alpha
with what we had before so that we see both of them. And now we need just one thing,
which is the inner diamond field, which is, again, another box. And this time, instead of using
the outline, we use the field. So it's field. And it's a bit smaller. And we just combine this. So, basically, now we use the three
boxes, a rotator, and the scale. And we have all the
alphas that we need to also use them with the colors. And now it becomes a
Lerp frenzy because we used the masks that we have created. So we have our diamond and we say,
OK, where there's the diamond, make it this greenish color. And there's the progress,
make it this light blue color. And for the rest use this gray color. And so, here we have it. It's just an animated
capture objective marker. This is the final material. And you will notice that
we used no textures. And this matters
because we are saving memory, which we can
use for other textures, maybe textures that are
cooler that we really need. We don't need to worry about
the texture resolution. And it's just easier to animate
because animating a parameter is just easier than trying
to animate a texture. And all these values
that we can tweak really give us a quicker iteration
time because we can just tweak a parameter. We don't need to
re-export the texture and then re-import it in the Engine,
and then see the stuff update. We can just change literally a
number, and we see what is changing. So I hope I teased you a
little with how it works. And now I really invite you,
if you haven't done it already, to download the project. It is free in the Marketplace. And it comes with a tutorial. The tutorial is in three parts. The first part is an introduction. It explains to you basically
what I explained to you just now, how to get the project,
and how to use it. And then, second part
is a huge documentation with all the material functions. So it explains inputs and
outputs of all of them. It shows you what it looks like. And it also gives you additional
examples and explanations. And the third part is just a list
of interesting combinations, so ways you can combine these material
functions in ways that maybe you didn't even think about. And this is supposed to be
some sort of living document where we will add stuff as soon
as we think about new stuff. So let's just open the Engine. And so, if you download
the project, pretty much this is what you should see. You have your material lab folder. And you have a bunch
of other folders. First thing I really suggest
you do is just press Play. If you press Play, you
will have a bunch of cards. We sorted them into categories. And I will not go
through all of them. I will not explain all of them. We have a documentation for that. And some of them, I mean, the
examples are there for these. I will probably just explain some
concepts behind some of them. So we have our transforms here. We have our gradients. And all these gradients,
they actually work-- they can be plugged--
they can be remapped with this remappable
gradient function. That works very much like
Photoshop or Illustrator. Whenever you added the gradient,
you can just move the values around to make the gradient
the way you like it. And this is how this function works. And then we have time. So I'm just going to show
you something about time. I'm going to make a new material. And I'm going to use the
user interface domain. So I want to just animate something. So let's draw a circle. I will use my SDF circle
function with the field. And this is what it looks like. Maybe smaller would be better. And now I want to show you time. This is our material
function, linear time. As you can see,
there's three outputs. So I just want to animate this circle
from this corner to the top right corner. So I use translate. By the way, another way of
seeing all the material functions is you can just right-click or tab
when you're in the Material Editor. And you find the UI
material subcategory. And you have all your functions here. And as you can see, they
all have a naming convention where they start
with MF underscore UI underscore the name of the function. And also, quick disclaimer. Some of these functions
are referring to functions that we already have in Engine, like
the rotate is the custom rotator that is already in the Engine. It hasn't been created
in the UI material lab. I just felt it made sense
to include it because it's a tool that you can already use. But at least, now you
have a method-- a method on how you would chain these things. And it makes sense that we
would include some of them. So I wanted to translate my stuff. So from my UV output to a UV input. And this is how we chain everything. Basically, we always have a UV
input and output everywhere. And that's how we can just
chain everything together. So I give it the starting
point, which will be, actually, I don't need a factor two. Just one will be enough. So this, just move it down here. And I will turn it into zero,
five, I have to move it up here. So what I do is I Lerp
between these two values that I found, the zero, five
and the minus zero, five. And then we use the linear time
as my value that will animate. And so, we'll go from minus
zero, five to zero, five. And so, my first output
is the zero, one loop. So as you can see, it goes from
zero to one, back to zero to one, and it keeps looping. Also, I can increase the speed. Maybe zero, five is better. And then we have ping pong,
which goes from zero to one and back to zero in the same time. And then we have switch, which
just is either zero or one. So this is our linear time. And it's not over, because
this time is linear, but we can change the speed
curve of our animation by using our easing functions. So we have a material
function called ease curves. And, basically, there are a bunch
of easing functions out there. We included sine, cubic, and quintic. But there are more that you can
find and that we will probably add in the future. But the way it works is that you
can easily combine linear time with our ease curves. You just take your
volume, my loop here. So this is what the normal
linear time looks like. And let's make it
slow at the beginning. So this just changes the
character of the animation. And it has different types of curves. So ease in, ease
out, and ease in out. And we will also see later
how this is not just for time. But you can use this
also for other things, like for gradients to change
the hardness of the gradient. And then, probably, my favorite
effect, is the time displays. I say my favorite, because it
is really simple in concept, but so versatile. So the idea behind
the time displace is that you have an animation,
some value that is animating. But you just want to give a
delay to part of this animation. So let's just look
at this blue box that is animating from top to bottom. We want to combine
this with a delay mask. So we will use, in this case,
it's a horizontal linear gradient. And what the delay mask does is you
set a value that you're animating. In this case, the
vertical translation. You set an offset, which, I
don't know, could be zero, five. And then you put a mask. And where the mask is black, so it
is zero, there will be no delay. And where the mask is white, there
will be the delay that you set, and all the values in between. So if you apply this delay mask
to this animation, what you get is these slanted animation, because
the more you go to the right, the more delayed the animation is. Maybe more interesting
it is with the step, the gradient in the second
example, because then you can really see the different chunks
animating at different delays. And the mask can be anything, really. In this case, for example, we
have a box that is rotating. And we combine it with the
time displays and the delay mask and the radial gradient. So in the center, black, which
means zero, which means no delay. And the more outwards we
go, the brighter the mask is, so the more delay we have. Which means that these
corners of the box will just be delayed
compared to the rest. And we get these Shuriken
galaxy spiral sort of thing, which is also pretty much
this example, this fifth example that we have here. It's a bit embellished. And if we go on, we find the SDFs. So SDFs are just the
best thing in the world, because you will see right now. So SDF stands for
signed distance field. So when you have to draw a shape,
you're used to using a texture. So you would have this
texture with, I don't know, a white triangle on
a black background. But you could replace
this texture entirely with a primitive, so
like circle, triangle, box, that is calculated with math. And so, there are some
differences, of course. Instead of having a mask, like
a white on black, for example, you would have a
gradient as an output. And this gradient, in
this gradient, each pixel is expressed as the
distance of this pixel to the closest point of
the shape we want to draw. I will explain better. So let's take, for
example, this circle here. So the circle I want to draw
is a circle of size zero, five. It is this magenta circle here. So what this SDF outputs is zero for
each point that is on the circle, because the distance of that
point from the circle is zero. It is on the circle. And the further we
go from the circle, the higher the distance becomes,
so the higher the value, which means the brighter. And these are called signed,
because when the point is inside of the shape, it has
a negative distance. So it has a sign. Of course, you don't
really need to know the math that is going on here,
because you have a material function that does it for you. And the material function already
has the smooth step applied to it. So it does output in the normal
field and outline outputs. It outputs your white shape
on a black background. But why is this relevant is
because we're not using a texture. So as I mentioned before,
the memory is happy. But also, because of
their nature, SDFs come with really some
interesting properties. If you see this square at
the bottom, the further we go from the shape we want to
draw, the rounder the corners become. So you can easily
get rounded corners. You don't even have to worry
about the shape getting bigger, because we compensated that
already in the material function. So you just have the same
shape, but we round the corners. And since this is a gradient, you can
use this to make a glow or a shadow, anything that needs-- we can control the level
of blurriness of the shape. And then there's another super cool
thing, which is the wave effect. So let's look at this highlighted
part in the magenta square. And as we said, this is a
gradient because it's a distance. And let's say it's a zero to one
range, which probably it isn't. It's probably from
zero to zero, five. But for simplicity, let's
say it's from zero to one. We can do some math with this. We can multiply this by a number. Let's say four in this case. So now we have a zero to four range. And we can apply more math to it. For example, if we do a
Frac, what we're doing is we're splitting this into
four different chunks that go from zero to one. And imagine doing this for the
entire container, so for every pixel. What do you get in the end is these
concentric frames that you can also animate, and they look very cool. And if you don't
want to use Frac, you can use many other operations to
give the shape different looks. And if you want to see it in
action, it is this function here. And we will also see it
in action in the demo. So I mentioned the glow. I mentioned the shadow. Each SDF has the stroke output
and can have rounded corners. Also something cool,
if you're already used to working with shapes in
Illustrator or wherever, of course you know that you can combine,
intersect, and subtract shapes. And you can, of course,
do this with SDFs as well, but with an added perk,
which is with some math magic you can have a smooth
blending of these shapes. As you can see in the second row
here of the Boolean operations. And so, it gives you
this liquid feeling. And you can also control how
much it smooths the blending. So I don't know, if your next
project is a lava lamp material, you can probably use this. And this is just an overview
of the SDFs that we made. I mean, that we added
to the material lab. So we have the box. We have triangle,
circle, and hexagon. And we will probably
add more in the future. And you can really see
how just by changing the parameters that
we have, we can have so many different versions of this. And we can have many
different usages for them. And how easy it is to animate
from one to the other. So you, say you have a button
that has straight corners. And when it's selected you want
it to turn into rounded corners. That's very easily done by
just changing one parameter. And in the last row,
you can see how you can do a union, a subtraction,
an intersection, and how it changes when you make it smooth
compared to when it's not smooth. So I think that's really cool. But going on. Ah, one thing, actually, is, I
did mention SDFs as a replacement for textures. But, actually, you can also
make distance field textures. You have to create them. You have to make them yourself. And in the documentation,
in the SDF section, I also link an article
that explains to you how to make them in Photoshop. There are also plugins
that can do that. But, basically, in this case, it's
not signed because it's a texture. So you can't have a
negative value on a texture. But they do share many
of the same properties. So this is what the distance
field texture might look like. And like we do with the
signed distance fields, you can use a smooth step and just
control the glow min and glow max to change the sharpness of the shape. And it can share the same
properties like during an outline, or having it-- making a glow, or a cool blending,
or even morphing between them. So it's not necessarily that you
have to replace all the textures with distance fields. You can also have
distance field textures. And they have the added bonus
that you can make them smaller. Because of the way
you can sharpen them, you can actually get them a lot
bigger than the texture actually is. So that's very interesting. Then we have the mask section. I mean, masks, I really just
invite you to just try them out. They have so many different usages. Read the segments is very useful in
combination with the circle outline because you can get this
segmented progress bar. And checkers is very useful if
you combine it, for example, with grid tiling,
because then you can alternate what you show on the
different cells of a grid, which we can see here. I don't know if it's very
visible in the stream. But we're basically tiling in
a grid hearts and diamonds. And we're alternating when we're
showing hearts and diamond. So in this case, we combine the
grid tiling with the checkers to determine what to show. And speaking of tiling, we also
have hexagonal tiling, which also outputs hexagonal pattern. And then we have also
different types of patterns. Half-tone is basically a grid tiling
where in each cell there is a dot. You could actually
put anything in there. You could put squares. You can even put little OXO faces. You could definitely do that. And it works with any input gradient. So if you see third example,
the one with the OXO picture, where the gradient is
darker your dot is smaller. And when the gradient is
brighter, your dot is bigger. So it's a very easy way to stylize
something with a half-tone look. And then we have a
tab for distortions. Slant skew, wave warp is very
cool because you can just distort the UVs with a sine wave. And then we have polar coordinates. So polar coordinates are
interesting because we are used to expressing
the position of a point with Cartesian coordinates,
so the point as to values. And these values are the distances
from the two axes that we decide, so the y-axis and the x-axis. But that's not the only coordinate
system that we can have. We can have radial coordinates. And what the polar
coordinates function does is it translates from one space,
from the Cartesian to the polar. So what visually it
looks like is it's like you were wrapping your
polar coordinates, or sorry, your square coordinates onto a
globe, and just looking at them from the top. Something really
interesting about this is whenever you have a horizontal
or a vertical translation, they become something
different in polar coordinates. And so, you can see, for
example, the green line here, vertical tessellation becomes
an expansion around the pole. And the red line, which is
the horizontal translation, when it is in polar coordinates, it
becomes a rotation around the pole. So that's how we made
super quickly this render. It's just a grid with two
lines that are moving. And then you put it
in polar coordinates, it becomes some sort of radar. So that's also cool. And then we have a tab that is
utilities, which are functions that, on their own, maybe
they don't do a lot, but you probably will use
them a lot in combination with others, which my
favorite is ping pong. So ping pong takes a gradient
that goes from zero to one and makes it go from zero to one
and back to zero as many times as you want. So it's very useful for repeating
gradients and for everything that you want to repeat actually. And, finally, the
applications tab, which is where we have all our widgets. So if you, for example, if
you're looking for a base widget, I don't know, you want to check out-- there's lots of examples. These are some inventory slots
that can have an active state. And they also have a hover state. And you can active. I don't know, maybe you
want to, I don't know, equip an ax and a
shield or something. And these are the objective
markers that we saw in the example. Progress bars that use SDFs,
small stat indicators that also have these tiny bubbles that go up. I mean, there's lots of examples. And I invite you to just
take a look and just see if something inspires you. And I think we are done
with the walkthrough. And, yes, it is demo time. So now I would like
to show you something. I have thought about
what am I going to show? In the end, I came up with this idea. Maybe I can show you a button,
because we have buttons everywhere in UI. And maybe we just want
some cool animation and we want to use lots
of material lab functions. So this is our button. And as you can see, it's like a box. But it is slanted,
and it has these lines that move from the edges outwards. And then it also has-- I don't how visible
it is on the stream-- but it has a sheen that
moves horizontally. And so, yes, that's what
we want to start with. So the way we would go with that
is, let's check out what we have. So we said we want a box. So let's use the SDF box. And we have a function for
slanting them, so presenting UV, so we can apply it to our box. And I think we can use
the wave for the lines. Yes, I think we can start with this. So this is the material
that I created before. So let's start with the box. So SDF box. And this is our box. I want the preview to
look more like a button, so I'm going to just
change the size of it. So this is our button. So size of the button, let's
make some parameters for that. So button size x. So when I don't have many parameters,
I like splitting the x and y sizes, just because it's more handy. But when there's lots of
parameters, maybe you want to group them into just one vector parameter. So maybe zero, seven and
zero, seven for the moment. And you turn them into a vector two
by using the append vector node. So this is more like
the size we want. Now we want to probably-- something that I do a lot is I like
to use reroute nodes because I like to keep everything tidy in chunks. So I'm going to call
this button shape. And this is what it looks like. And I'm going to plug this-- I want this material
to be translucent because we will need the alpha. And for the moment, I
will just do opacity. And I will just assume that
the whole button is white. And we think of the colors later on. So this is our button shape. Now we want to slant it. And let's just use the slant
material function from a UV output to UV input. And it's maybe too slanted. So we want to give it a
different amount of slant. So we can slant horizontally,
or vertically, or both. So we need to slant
just horizontally. So we're going to make a vector two,
where the vertical slant is zero. We don't want vertical slant. And the horizontal slant
is another parameter, which we will call slant amount. And I think zero,
one will be a good-- maybe zero, 15. Yeah. So this is our slanted button. Already we are somewhere. Now we could make these waves here. So let's check out the
wave material function. As you can see, it
needs an SDF as input. So I can't just plug the field there. I will need to use the SDF. So, again, I like
storing this somewhere. I'm going to call this button SDF. This is what the SDF looks like. So it's a gradient. And the inner part here, it
looks black, but it's not zero, it's a negative value. So this-- I mean,
shouldn't bother you if you use the normal
field and outline output. But if you have to
manipulate the SDF, you need to remember that the
range can go from minus one to one. So this is our button SDF. I am going to input it to the wave. And let's see all the different
outputs that the wave has. This is if we use the
cosine as an output. This is if we use the ping pong. And this is if we use the Frac. I think I will go with the ping pong. And, of course, I want to sharpen
it, because now it's just a gradient. So I will use smooth step. And let's try and see what
values we need to input in. Let's try zero, one. And whenever you use smooth step,
the hardness of the smoothing is always depending on how close
the min and max values are. So first, actually, I want to try-- I want to find out
what that value is. Let's see I start with zero,
four and maybe zero, five. I think this is a nice
smoothness of the lines. So I know that there has
to be 0.1 of difference between the first and the second. So now I can do this
more automatically. So I will input this. And then I will use the same
but with plus 0, 1 for the max, so that now I can really just
find the value that I want. So zero, one. Let's use zero, four for the moment. So I found the wave. And I want to combine the alpha. So I will use the max node. It's already looking like something. But I don't want this wave
at the top and bottom. So I think I need to mask it out. There are different
ways I can go with that. I think, just out of simplicity,
I will just draw another box. And this box would be the same
height of my first button shape but will just take the whole width. So we'll just duplicate this box. And I will take these values. So I will need-- I'll reroute for this. I don't know if you noticed. I hate having spaghetti, so
I use reroutes everywhere. So we call this button size y. And I will use it here. And the size x, I could
go with a super safe 1.5. One should also be fine, but OK. So this will be the mask. And everything that is black will
be cut from the shape of the button. So I will call these vertical bounds. And I will use this in
a min because we want to just keep the thing in between. So what happens when we combine
this stuff with the mins is that we just cut
the top and bottom. So already looks much better. So one thing that we want to do now
is if we look at this, the lines, they start thick, but they
become thinner over time, or the more they get far
from the button shape. So that's what I want to do now. So, basically, what
I need is this value that I found, the value
of this smooth step, I don't want it to
be a constant value. I want this value to change depending
on the distance from the button shape. So what is the distance
of the button shape? It is our SDF. It's already giving us a gradient. So we can use this as a base. So as I mentioned before,
SDF has negative values. So if I have to use it in a
Lerp, I need to first clump it between zero and one to
not have unexpected results. And that's what the
saturate node does. It does make sure that
whatever input will be clamped between zero and one. So I will use this to
Lerp between to values. These two values will be how
thick the line is at the start and how thick the line is at the end. So at the start, I
think we could go-- yeah, with a zero, one value. So we can start with zero, one. And at the end-- or let's do zero,
nine for the moment. Let's see what this
looks like if we plug it. I think it's not bad. Maybe zero, nine is too much. Yeah, zero, eight. And I should probably make
some parameters for this. The scalar parameter, I will call
these wave min size and wave max size. And we said it's zero, eight. Let's just tidy up a little. So let's group this. And we call this button shape. We call this wave. And we call this cut top and bottom. So what's next? I think we need to fade the
button at the extremities. So what we could use
for that is we can use a linear gradient that goes
from zero to one and back to zero. So ping pong. So let's use linear gradient. So this is our linear gradient. And let's use ping pong. And this is what it does. So instead of going
from zero to one, it goes from zero to
one and back to zero. Let's call this horizontal
fade, because that's what it is. And so, we can use this
here to fade the alpha. So with another min, because we want
this to be intersected to the alpha. So it works correctly. But there are two issues. First that the gradient is not
really the gradient that we want. It is just too bright in the
middle and fades too quickly. And second, we might
want this gradient to be slanted together with the UVs. So I'm going to recycle these
slanted UVs that I'm using here. I'm going to call this
slanted UVs. And I'm going to use these UVs
for our gradient as well. So first problem solved. Our gradient is slanted. And now I want to change, so to
change the range of the gradient. So something we could do is we could
just brighten up all the values so that the white
takes up more space. And to do that, we
can use a multiply. But of course, if we multiply,
we make them go out of range. So we also saturate, keep
it in the zero to one range. So already not bad. I feel like the shape
of the gradient could be different, could be a bit better. And that's how I would
use the ease curves. I promised you that there were
other ways other than animations to use ease curves. And I was serious. So let's try out, for example,
if I use this, ease out. See, I changed the hardness of the
gradient according to the curve. And, actually, it looks a lot better. Actually, I might not
even want to slant it. Yeah, I think it looks
better not slanted. So this is done. I'm going to call
this horizontal fade. What is left to do? Yes, we have these two glowy
lines at the top and the bottom. So, again, different ways
we could go to make these. And, again, I will
go out of simplicity, I will just draw another box
and just take the outline. And I could use this glow lines. I could use this outline here that
I used for the vertical bounds. But the problem is that
in order to make it glow, I need to change the glow
min and glow max values. So I'm going to show you. For example, to make
a shape more blurry, I can just increase the glow
max, which is zero by default. So by default, is completely sharp. And if I just change this value to a
higher value, it gets more blurred. For me, if I do this,
also the vertical bonds are going to be affected. So just for the sake of simplicity,
I'm going to just make another box. I'm going to make another box here. And it will also-- it will be the same. It will have the size of the button. And then it will just
take the whole space. Now I can control glow min and max
without affecting the other one. What did I call this? I called this glow lines. And let's just find the
right parameters for it. Gonna show the border. So now, we also want to control
the thickness of the stroke. So let's start with the stroke
thickness, zero, zero, five, zero, zero, two-- it was zero, two. And the glow max could be zero,
zero, one, zero, one maybe? And maybe I could change this. These are all values that then you
tweak, and you maybe make a material instance, and you just change
the parameters real quick, and you find out the ones
that are working best. Zero, zero, five, not bad. Let's turn this--
everything into parameters. So we call this glow lines glow min. And we call this glow lines glow max. And now we call this
glow lines thickness. And these glow lines
need to be faded as well. Can I use the same
horizontal fade for it? Let's see. So if I do a min with the fade. Yes and no. Maybe just a linear one. Yes, better. So I'm going to call
this linear fade. We're still recycling. That's not exactly
the horizontal fade. But we're not adding a new function. So we have this. And so, these glow lines,
whenever I do a glow, instead of using a max
node, I like using an add, just because it gives a
different effect that is more to do with adding light and stuff. So it was glow lines. But, also, whenever you add
stuff, and there is the risk that you go out of range or
waste a saturate afterwards. Maybe we can boost the
opacity of the lines just by multiplying by a value. I don't know if you
can see my screen, but I can see that it
gets boosted a little. And maybe we can play
around those values when we have the material instance. So this is also done. And I think we've done
everything in terms of masks. And now we can go to colors. Which are just the easiest part,
because this was just finding-- they depend all on the masks. I will call this glow lines. Now we have all the
masks that we need. So let's start with the
base color for our button. Left parameter, and we
will call this base color. And I feel I have to say,
I'm not a good artist. So the things I do, they
are very functional. But I'm sure that artists with these
tools can do a lot better things. Anyway, base color. So this is where we start with. Of course, we don't want
everything this color. We want to-- since, again,
we're dealing with glow, we want to add stuff in additive. So what we want to add
is the glow lines on top. And maybe not just
with a saturate always. Maybe not just the
glow lines like that, we want to multiply them by
a color so that we can just add a color in additive. And we can call this color glow
lines color, which is already better. Then, of course, we need
to find the right colors. And, yes, the sheen that we
were talking about before. So first we have to make the sheen. So let's make the sheen. So this sheen is just a mirrored
gradient that translates, that pans horizontally. So that will be easy
because we already learned how to do that linear
gradient with, you guessed it, ping pong. And we do want to slant
this one because it needs to follow the slant of the button. So we have our slanted
UVs stored in our reroute. And we just do like that. And we want to pan it. So you can use a
panner, but I'm going to be faithful to the material lab. I'm gonna use the translate
function of the material lab. So what do we want to translate? We want to translate horizontally. So let's make a vector
two where, vertically, we are not changing anything. And horizontally, we are
animating using linear time. And [INAUDIBLE] would be fine. How does this look? It seems OK. So we'll call this sheen. Stop previewing this guy. Idea. Sheen. And now, just like I
did with the glow lines, I'm going to add it in additive
because it's a sheen, so it's light. So it's added. And as I said before,
saturate after adding. So let's make a new color for the
sheen, sheen color, and multiply. And let's take the sheen
alpha that we just made. So this is what it looks like. We add. We saturate. And then we do this. Maybe let's make it a bit
brighter so you can see it better. Yeah, I think you can
see it better now-- I hope. And I think we are pretty much done. We might want to change
the speed of the sheen, maybe using a parameter,
sheen speed, because we might want this to be a bit faster
or something, so zero, four. So let's use this as a base. Let's make a material
instance out of this so we can tweak all the parameters. And then we are pretty much done. Yeah, I am forgetting naming
conventions for this example. So this is our button. Just want to check if everything
works the way it's supposed to. So if I change the size, the
button changes accordingly. Can I change the slant amount? Yes, and everything seems
to update accordingly. So let's just tweak
these glow lines here. I had an intensity? Ah, no. I hardcoded this value. So these are the glow lines. And I give them a little alpha boost. But I want this to be a parameter. So I will call this glow
lines intensity, which would be two by default.
But then I would be able to change it from
the material instance. So now I see it here. So you see that if I change it, they
get more intense or less intense. And I can tweak maybe the thickness
of the line with glow max. And then, if I change the
wave min and max size, I can change the
falloff of these lines. So, for example, if I want
them to get thinner quicker, I can increase this value. But it is probably too much. But maybe zero, nine is nice. [INAUDIBLE] I don't know. Maybe I liked it better before. So when we talk about animating
this, we could make a widget. So I see three animation phases here. One is that we see
only the two lines. And then, we see only the diagonal
lines, and then the bottom opens up. So the way we can animate this is
we can start with the button size. Yeah, so this is what it
would look like closed. And then it can open up like this. And then, let's see what
we can do to animate this. So we just want to
display the glow lines. Which means so we might want-- ah, maybe we can change
the horizontal fade. Do we have it as a parameter? No. Ah, we have it here. We can make a parameter out of this. So the moment we multiply this
by zero, the fade will be black. So it will mask the entire
thing, excluding the glow lines. So I'm going to make
a parameter for this. And I will call it
horizontal fade intensity. It should be two by default.
And then we can tweak it. Let's see if it works. And it does. So now we, really, we have everything
that we need to animate this. We can make a widget Blueprint. Use your widget. And we'll call this button. And the naming convention
is WPB for widget Blueprint. So let's add an image for our button. And our image will be-- well, what we used as a
preview, so 500 by 80. And then we assigned the
material instance to it. So where did I save it? In the demo. There we have our button. So let's make-- I will call
this image button background. Let's create that animation. So animation, let's call it. Let's say button intro. So what the button which-- we don't need the
word button, actually. Just intro should be fine. So what the animation that will play
when the button appears on screen. So let's choose a track to animate. So in this case, we want
to animate the image, and specifically want
to animate the material. And specifically,
we want to animate-- so what did we say? We want to animate the button size
x and the horizontal fade intensity. I think those are the two parameters. So this one, the mission is
a bit too long for an intro. Zero, zero, five? Why not? So the way I see it, we can
split it into three parts. First part, only the glow lines. Second part, only the diagonal
lines and the glow lines. And third part, it expands. So that's the way we go about it. So for the first part, the
button size will be zero. So this is what we see. And the horizontal fade will be zero. So we see only the lines. And what happens is
that in the first part the horizontal fade becomes one. And this is still zero. And then, for this other
third, this becomes one. Let's see. It's a bit too fast. Maybe we can just make
it a little longer. It's an intro. It can be a little longer. So it is 60. So the first 20 and then 40. So bam and then bam. And here we could have-- oh, actually, no. Actually, we want
to finish like this. And then, at the beginning, we
want the glow lines to just appear, so fade in. So they are one Be zero. And here-- a, the whole opacity. We have a parameter for the fade? Glow lines intensity. Yeah, we can make them
disappear completely if we want. So the default value is 2.5. So we want them to become-- I want to animate them so. We said that it's a
glow lines intensity. So it would become 2.5. But it will start as zero. So first part of the
animation, they come in. Second part, the lines come in. Third part, the bottom opens. Horizontal fade intensity,
was it one by default? Now, two. Supposed to be two here. Makes more sense. This is our animation. I think it's not too bad. Bottom size x is not supposed
to be one at the end, but it's supposed to be zero, seven. Now it makes more sense. Yeah. So this is how you can
then animate it in UMG. So this is your animation. And then if you want to call this
animation from the Blueprint, I don't know, when the
widget comes on screen, you might want to do
it on the construct, you take your friend animation. You do a play animation. I can do this. And you're pretty much done. Then, of course, now I don't have
this guy playing in the scene. But then what happens is
that the animation will play when the widget is constructed. So I think that we are
done with the demo. I had a second demo,
but I think I would like to leave more space
for the Q&A. So this one was the second idea I had for the demo. But I think the button
is definitely something that you would use more often than
this specific background pattern. It was just a way to show you how to
use the random and the checker mask. But there are so many
examples in the material lab that you will find something
similar to this anyway. Before closing, wrapping
up, I'd like just to talk quickly about the next steps
that we have for the material lab. So, of course, now, enjoy it. Experiment with it. Play with it. And what we are
planning for the future is, of course, more
material functions, especially according to your request. And I will show you just
in the next slide how you can request new material functions. But then, we also want
to have font materials. We want screen space effects, because
we didn't even talk about those. And we didn't talk about
Vertex offset animations, and those reveal mask. And something that would be
cool is function cost tags, which would be, I don't know, three
tiers of how expensive this material function is so that people know if
they can span this like a translate, or if they maybe should
be a bit more careful. And, of course, whenever
I talk about performance, always take it with a
grain of salt. It really depends on your game, and your
needs, and always profile. But in general, we
could have these tags that just give you a ballpark
estimation of this material function, not to be
messed with too much. Thank you very much. If you want to give some feedback,
if you want to request a material function, or report something
that maybe is not working, you have different
ways of doing that. You can leave a comment
in the Marketplace asset or on the Twitter page. Or you can also email me directly. And, yes, we are planning for
more updates in the future. I can stop sharing. And I hope this was interesting. I don't know. TINA WISDOM: It was. This was incredible. I wish I could get all
of the love from chat just into here where you can see it. But everyone is just
talking about how amazing of a presentation that was
and how much they learned. IRENE ZANON: Yay. TINA WISDOM: So thank you so much
for that, especially that demo. I think being able to actually
walk through it step-by-step is incredibly helpful for
being able to break down demystifying some of those nodes
and how they can function and work. So thank you so much for that. That was incredible. IRENE ZANON: I'm glad
it was appreciated. I don't know if, Pavlo, you wanted
to add something to the presentation? PAVLO GRUBYI: Yeah, this is awesome. Thank you so much, Irene. This is great work. And I heard that from
our colleagues in Slack right now, if we would
have this material up at the beginning of our careers,
it would be much more smoother for us to implement all those tools. IRENE ZANON: Yeah. I think so too. Because we're really all pretty
much self-taught on materials. And we may just make so many
mistakes along the road. And if people can just avoid making
the same mistakes that we did, or just kickstarting, just
getting up to speed quicker, that just would be amazing. TINA WISDOM: Yeah, absolutely. I mean, I know that UI is-- it's kind of a blind spot, especially
when it comes, like you were saying, to tutorials or documentation. So I think, really, stuff like this,
the project, the tutorials that go along with the project, as
well as even just this stream, are huge strides in being
able to catch everybody up past some of those beginner
steps so that people aren't all just starting
at the bare minimum and trying to learn from there. And they have a
foundation to work off of. So I very much appreciate
you taking the time to actually set all this up. IRENE ZANON: That was
my pleasure, really. Are there any questions
that we might help with? TINA WISDOM: There are. There are a few questions
that I will toss y'all's way. The first couple of ones
that I want to go over are a bit more overviewish of
not necessarily the material labs project itself, but maybe
just the concept of UI in general, if you're comfortable
with answering some of those. IRENE ZANON: Yeah, sure. TINA WISDOM: The first one
was, they were wondering if you had any advice on, if
they were a beginner in UI, now that you've provided
a project for them to experiment in, what is
your advice on them from here? What should they do now that they
have their hands in this project to continue to learn and push forward
in increasing their knowledge? IRENE ZANON: Oh, that's
a great question. The first thing that comes to
my mind-- and, of course, Pavlo, I will also let you
answer just afterwards because I think you might also
have a lot great insight on this. But something that I
would suggest is just, if you don't have right now a
project that you have to work on-- because a lot of things
you learn them hands on, just by making things,
making projects. And if you don't have right now
a game that you're working on, just find some UI that
you see on another game and just try to make that. Actually, if I can share
my screen real quick, I was doing that just
a couple of days ago. I was seeing my partner
playing Destiny 2. And I noticed that in your
inventory, when you have a new item, it has a shine. It has this sheen that appears. And it has this tiny very thin frame. And it is a subtlety, but
the sheen in the frame is delayed compared to
the sheen in the sheen. And I thought, whoa,
that is time displace. I could do that with a time displace. So I tried to replicate it. And this is my sheen. So this would be my mask
in the time displace. And the value that I'm animating
is the translation of the sheen, so the sheen moving diagonally. And my offset is one in this case. So what happens is that the sheen
is delayed only on the frame. And I just thought that was
such a subtle thing that just gave so much character to it. Because if I put the offset at
zero, so I remove the delay, everything still looks good. But the moment I add the delay,
it has that something more. So something-- and I'm done
with the screen sharing. So something that I
would like to suggest is just find some UI
of some game that you like and just try to replicate that. Because that will give you
a lot of real-life scenario. And you will face challenges. But, yeah, that is one
thing I can think about. I don't know if, Pavlo, you
have some other suggestion? PAVLO GRUBYI: I totally
agree on that one. I remember the time when I was
trying to remake the Overwatch UI. And at the time, I found it
has this very cool tilted-- it looks like the UI,
the parts of the HUD, are in the world space distorted. And when I was trying to mimic it,
it appeared that they actually just tilted there with just like that. There is not a curve,
there is nothing like that. It can just tilt your
widgets just seven degrees, and it looks like it is bent. And that's a great trick. And I realized that only
by trying to redo that HUD. IRENE ZANON: Yeah, I agree. I totally agree. TINA WISDOM: That's awesome. I honestly wouldn't have
even necessarily thought of that, of just going in
and finding UI that you like and trying to recreate
it, build it backward. How was this made? That's a great way to approach that. IRENE ZANON: Yeah, I think so. TINA WISDOM: Awesome. Another question that
we've got here is for anyone that's trying to
create their own bespoke UI, should they start with
some kind of a sketch or some kind of an
artistic asset to start with as a visual of
what they're going for, or just go in and see what happens? IRENE ZANON: What
would you think, Pavlo? PAVLO GRUBYI: Having a plan
definitely would make this faster. So at least to have a wireframe
or a mockup, if you have that. Or maybe you can find
something on the web that you would like
to, again, to repeat. But starting out straight from
the Editor may be a bumpy road. Only if you are working on a system
or something that doesn't really need to be presentational,
that may be the way. However, if you're working
on something visual, you should at least know
your goal before starting. IRENE ZANON: Yeah, I agree. I think it is necessary, at least,
to have the UX of what you're trying to do sorted out so you know-- I don't know, if you're making
a whole menu, for example. It is important that you really
know pretty much the layout of it before starting to make the widgets. But as far as the
visuals of it, I think sometimes if you don't
have already a direction, you're doing your own
project, or you have lots of freedom in your project,
why don't you start experimenting? Happy accidents
happened, and maybe you weren't planning of something looking
the way you managed to make it look, but it's better. So I think to a certain
degree, so it's up to you, up with what you feel comfortable,
and what your creative workflow is. TINA WISDOM: Absolutely. Get some Bob Ross UI in
some of these projects. [LAUGHTER] IRENE ZANON: [INAUDIBLE] TINA WISDOM: Let's see some
of the more specific questions that we got in here. Have there ever been
any situations where you've had to simplify a UI
material for performance reasons? Or are there any particular nodes
that anyone who's a beginner might need to keep an eye out for? IRENE ZANON: Yes. [INAUDIBLE] So the thing that
I find myself the most is-- simplifying, is-- so one of the
most expensive things that you can do in materials is sampling
textures, in general, of course. I always talk in general. And in many, many cases,
you could replace textures with something else. And so, sometimes I work on Fortnite
with materials that already exist. And I just want to
maybe optimize them. And so, I manage-- instead of having a hexagon
texture, or a hexagon pattern, I can do the math. And I know that that math is
cheaper than sampling the texture. So that is something that we do. As for nodes, I actually
didn't talk too much-- when I was talking about
the polar coordinates, I should have mentioned probably
that the way normally people would go with that is they would involve in
their operations the infamous eight and two, which is the most
expensive mathematic-- I think the most expensive
mathematical operation that you can do in a material. But you don't have to worry
about that with our material lab, because it uses a cheaper
approximation of it, which it-- is a node present in the Engine
is called eight and two faster. And this-- an approximation
that visually you don't see any difference. So we can totally use that. If you really needed
the extra precision, maybe you would want to
use the original function. But that's something
that we keep in mind. In general, simpler operations
are like add, multiply, min, max. I think also Frac. The way you measure
performance is always relative to everything
that is going on. So you should profile to see if there
are some bottlenecks in what you're doing. So if you see that
there is a material that seems to be pretty heavy
to render, or textures that are occupying lots of
memory, then maybe that's what you want to focus on. But in general, operations are
measured in terms of GPU cycles. So how many cycles it takes to
the GPU to complete the operation. And, definitely, it
also depends on the GPU, because GPU has
different architectures. But, generally, the simpler
ones are, as I said, add, multiply, seal, floor, min, max. And then we go a bit more complex
with smooth step, with sine, cosine. Trigonometry is not super cheap. And then, when we go in inverse
trigonometry, arctangent, arcsine, arccosine, then we go
even more expensive. But still, I would maybe
recommend an arctangent too rather than sampling a texture. Of course, it depends. But in general, it just depends. Are you on mobile? Do you have memory constraints? Then try to free up memory. It really depends. But, yeah, maybe that's
where the function cost tags would come in handy,
to just have an idea of, hey, this function is expensive. So, yeah, depends
on the architecture, depends on the context, profile. My answer is profile,
and you will find out. [LAUGHTER] TINA WISDOM: Awesome. IRENE ZANON: Do you
agree with me, Pavlo? PAVLO GRUBYI: Yes. In Fortnite, we have a concept
of the master material, where pretty much everything
you have on the screen is combined into a single
huge supermaterial. And having some for many years,
and people keep adding to that, we make it a beast. So we are trying to
remove the legacy stuff. And Irene is actually currently
working on one of those. IRENE ZANON: Yeah, the snake. PAVLO GRUBYI: She calls it the snake. [LAUGHTER] It is a huge snake of
50 material functions. So, yeah, there was a case. TINA WISDOM: That sounds intense. [LAUGHTER] IRENE ZANON: Because sometimes,
something that performance-wise is actually OK, it's just
not user-friendly to use. You just look at it,
and there is a problem. You see the problem. And maybe the computer doesn't,
because the computer doesn't care. But there are actual human people
that have to use these materials. TINA WISDOM: Right. [LAUGHS] I also really enjoy the fact
that there's the eight and two node that's really expensive. And there's literally just one
that's called eight and two faster. [LAUGHTER] IRENE ZANON: Yes. TINA WISDOM: That's amazing. [LAUGHTER] IRENE ZANON: It is. TINA WISDOM: Another question
that we have here is, I feel, kind of similar
to what you were doing with the button
near the end there when you were animating
through the parameters. But how would you
handle UI animations that involve multiple stages? Would each animation be made
in a separate UI material and then composited via Blueprint? And the example that
they gave would be like an experience bar that
hit a certain threshold and triggered an
additional animation. IRENE ZANON: Ah, I see. Well, there are cases where
you might want to split it into different materials. It also depends on
your widget hierarchy. If it is just better
overall for performance to keep a widget collapsed,
because you probably won't need it very often,
then it makes sense that that is a separate thing. So there are different degrees
of different animation phases. The one that I showed you with
the Blueprint and the animation Sequencer, I would say,
is an intermediate one where you have your phases inside one
material but animated in Sequencer. But you could also go all
the way completely material, where you take just one control
which is animation duration. And inside the material
you split it into phases. And you use that
animation value as a Lerp, as an interpolator to
interpolate between states. Actually, I have an example of this. I mean, it's not a full example. But in the part three, where
we have the material function combinations, which, by the way,
have all snippets, code snippets. The snippets work only
if you have the material, because they refer to the material
functions that are in the project. But I am showing
something-- where is it. Well, let's find it out by scrolling. So, for example, here I am Lerping
between three different shapes. What I'm doing is I'm taking time,
and I'm using stepped gradient. So stepped gradient, what
it does, it splits the input into discrete chunks. And we tell the step gradient
how many chunks we want. So our time goes from zero to one. And let's say we want to split
the zero to one into three phases. So we use a stepped gradient
to split it into three chunks. And then we cycle in-- this is a Lerp between three floats. So, yeah, there is
no multiple functions in the previews of the snippets. But, basically, we have our
linear time here plugged into the stepped gradient. And this goes as the
interpolator in the Lerp that Lerps between the
three different shapes. So this is the most
basic one because it just has a harsh transition
between the stages. But you could have a small
transition between them if you used the remappable gradient. So here, I'm showing the difference. Ah, yeah, it's probably clear here. Maybe I can zoom in a little. Doesn't seemed to work much. Ah, it does, OK. So here, you see that if I
use just the linear time, I will not have any states. The interpolator will
just go from zero to one. It will never stop on a specific
shape in the example before. You just keep transitioning
between the shapes. This is the example
that I showed before with the three different stages. But I can also have a small gradient
between the different stages so that it stops on a stage, and
then, just as a slight transition to the next one-- I don't know if it's very visible. But this third gradient
has a transition between the three different chunks. And this is achieved with
the remappable gradient. Because remappable
gradient-- is it this one? Yes. Actually, it's better if
I show it in the Engine, because without the names. I'm just going to borrow the
material that I created before. Ah, it's already here somewhere? Here. So remappable gradient
float in this case. So I input the gradient
mask, which could be the linear time if we want to. But just for visualizing,
let's use a linear gradient. So we input this. And we will need one,
two, three, four values. And I will explain to you why. And I will preview this. The multiplied by one is just so
that they can preview the node. So let's just turn everything to
default. So blah, blah, blah, blah. And then, just want to reset
everything so I can show you. So in Photoshop, what
you would have is if you wanted to make
these gradients here, you would need to edit a
gradient that starts with black. Then as a transition
between black and this gray. And then we have another
gray handle here. And then the white handle. And then the white handle. Or you can just have black
handle, gray handle, gray handle, white handle. I hope you are familiar
with Photoshop, otherwise this might make no sense. So let's just make those handles. So we need four values. As we said, black is zero. Gray, we can use zero, five. And we said gray again. And then we said white. And in terms of positioning,
we need these to be at-- well, a bit less than a third,
and this a bit more than a third, and is a bit less than 2/3,
and is a bit more than 2/3. So it will be zero, 32, zero, 33. And then we will have zero, 62-- 65, and zero, 66. So these will be plus value
one, two, three, and four. And I can show the border. And I can actually make
these gradients more visible. So I can maybe do zero, three. And, basically, when I change these
positions here, I'm just changing-- as if I was changing in Photoshop
where these handles are positioned. So if I make the handles more
far apart from each other, I will have a longer transition. So if I accentuate this, like
zero, two and zero, four, you see how this
transition is a lot more. And now you might wonder, but how
do you use that in a transition? So let's use a Lerp
between three shapes. Lerp multiple float. This is a function
that is in the Engine. And I want to preview this. And I want to Lerp between
a circle, triangle. Now, this is where
all the tidiness ends. And the box. This box, not just a box. Beautiful. And now I will use my
gradient four values here, which right now, of
course, says this, because we are using the linear. Again, we want to use
the linear time as input. And maybe if I change this L
250 by 250 we keep the ratio. So, also, I should use the SDFs
because they blend a lot better-- bam-- sorry, bam, and bam. And for the SDFs, then we need a
smooth step, as we said before. So, good. Let's see, zero, and zero, zero, two. And the one minus because
I want them to be inverted. So we had the zero,
two, zero, four, which has a longer transition, which
is the transition you can see between the triangle and the circle. So that is a nice transition. And then we have a quicker
transition, zero, 65, and zero, 66 between the other two shapes. So if you, for example, had not
the shapes but something else, like three values that
you want to change. For example, we
wanted our button size to be zero in the first phase of the
animation, zero in the second phase, and zero, seven in
the third phase, we could use these values
here instead of this. We just input our phase, so
zero, zero, and zero, seven. And so, these will be
our interpolated values. And we will plug this to
the button size input. And we will basically
animate in this button size as if we had different
animation phases. So this is one way of going about it. But then, of course, you
have something more complex, it makes sense to split
it into different widgets and different materials. Sometimes we have in Fortnite
some super flashy lightning, glow, and sparkles, and stuff,
and we do separate them. Although, yes, if you can, if
you find ways not to do that, that's also fine. Maybe a bit better,
but not a big deal. I don't know if I answered the
question or I went on a tangent. TINA WISDOM: I feel like that
appropriately answered the question. And it also taught some
extra stuff on the side. So if anything, it was
an even better answer. [LAUGHS] That was incredible. Again, I wish that you could
see the chats, because it's just everyone being so impressed of you
being able to pull that up and just make it in 30 seconds. IRENE ZANON: Bam, bam, bam. TINA WISDOM: Here you go. [LAUGHS] Here's the full transition,
start to finish, in a minute. It's fine. No big deal. [LAUGHS] IRENE ZANON: And we used only
material function and smooth step. TINA WISDOM: This is true. Honestly, this is making me
want to go into the Engine and just make a bunch of
UI for no apparent reason but just because it looks fun. IRENE ZANON: That's good. That's good. TINA WISDOM: There's just
a couple more questions I want to throw at you. I know we're nearing the
end of the time here. So I'm going to try
and make them quick. IRENE ZANON: No problem. TINA WISDOM: But there
is one question of, how many UI master materials are
usually needed and/or would you recommend as the maximum for a game? IRENE ZANON: Whoa. I don't know if I have an
answer to that question. Pavlo, do you have an
answer to that question? PAVLO GRUBYI: It depends
on your UI design, and how many screens and UI
features you have for it, and how complex those are. For example, we have features
that use only one master material, and we have features
that use multiple. But also, we are trying to minimize
the amount of [INAUDIBLE] materials because they are hard
to handle and support. So, yeah, it really depends on
the scale of the UI and amount of the people in the team. If you are alone, and you are
making it for mobile, and you need, I don't know, 300 fps on your
UI, then one master material for the whole UI is a go-to. IRENE ZANON: And the screen
that supports those fps though. PAVLO GRUBYI: Yeah. But once another
person comes and takes a look at your master material, make
sure that that person understands what is going on. IRENE ZANON: Yeah, and
I would like to add, if you have one master material,
it means you have one asset. But then you might have
material functions and stuff. But it means that if someone
is using that material, other people cannot use it. So especially if you
collaborate, sometimes it might not be a good
idea, if it's something that many people need to
work on at the same time, to have this just big giant monster
that someone checks out one day and other five people need
to use it at the same time. TINA WISDOM: Right. I know that's the
idea of other people might have to come into this
file later is a good mental note to have for most things. IRENE ZANON: Yeah, it
happens in all the games that I worked on that a big chunk
of what we do is work on stuff that someone else made. This is valid for every
discipline almost. It is valid for code. It is valid for UI, for materials. Sometimes the biggest effort is to
really understand first the system that you're working with so that
you can make some changes to it. So it is really important that
your stuff is understandable. That's why we have best practices. We have naming conventions, so
that we are all on the same page. And at least we have less
friction when it comes to working on other people's assets. TINA WISDOM: Absolutely. Only two more. We're almost there. Is there any way to create a
non-looping animation for materials? IRENE ZANON: I mean,
the answer is yes. I'm not sure exactly what you
mean by non-looping animation. We do have ways of triggering
an animation and having it stop. TINA WISDOM: I think it's-- maybe what they're
talking about is if we use the button you created, for
example, how the edges are always shifting back and forth. Would there be a way
to create that where it only does it a certain
amount of times and then stops? Or would it always
just continue to loop? IRENE ZANON: Yes, definitely,
there is more than one way. The simpler way is that you create
your animation in Sequencer. So your animation would be the button
that animate for a second or so. But there is also
other ways where you can trigger the
animation in Blueprint and have the material
do all the calculations. Actually, in Fortnite, we
have an experimental Sequencer that runs on material. I cannot really explain how it
works because I would need to open Fortnite, and I can't do it. And we don't have this material. It's an advanced thing. But if you are a
beginner, what I suggest is create the animation
in Sequencer and just play the animation when you have
to play it, like on the construct, if it's when your widget is
created, and it will play once. Yeah. PAVLO GRUBYI: If you're
interested in that technique, there is a talk by Adrienne Pugh,
who is also our technical UI design director. You can search for real fast, 1022. And on day one, she was
explaining how that works and showing off the
Blueprints that trigger those animations in materials. IRENE ZANON: Very, very true. It's the advanced templating
techniques presentation, Pavlo? PAVLO GRUBYI: That's right. IRENE ZANON: Yeah. TINA WISDOM: Awesome. Getting the link for that in the
chat right now, because that is also another incredible
discussion about UI. So if you want to learn
any more about it, please do go check out
that talk by Adrienne. It's incredible. So, yes, please check
that out as well. All right, the last question
I have for you all today. What are, in your
opinion, the most useful learning sources for
SDFs, or UV math, or just getting into this in general? IRENE ZANON: So something that
I find really, really useful. But you need to understand coding
because it is done in HLSL-- no, in GLSL, which is
very similar to HLSL, which is the language that
we use in Unreal Engine-- is the Book of Shaders,
which is a website. I know it says book,
but it's a website. And it has the basics. The example, in this case, will
not use Unreal Engine materials, but they will use code. But the functions are the same. The mathematical
operations are the same. You have Frac, you
have add and multiply, everything is there pretty much. There are some subtle
differences when you have to convert from
one language to another. But they are the same things. If it's specifically to
SDFs, in the material lab, inside the material
functions for the SDFs, there is a link that is, Learn More
About SDFs with Inigo Quilez, who is the God of SDFs. He's very famous in the
shader enthusiast community because he provides these
functions, and he explains them, and he shows examples. So there is additional
learning material inside the example materials and
the functions in the material lab. And I can post some stuff
additionally in the tutorials. So I will just make a
note that I will do that. TINA WISDOM: We're just
making more work for you. That's all. [LAUGHS] IRENE ZANON: I'm happy. [LAUGHS] TINA WISDOM: Awesome. All right. Well, then, I will see if I can
nab some of those links real quick to toss them up in chat. I know Book of Shaders
is in there now. And I'll see if I can grab
some of those other ones. But that's it for
the questions today. So before we wrap up, are
there any kind of last words? Ooh, this sounds ominous. Any final thoughts? Let me put it that way. [LAUGHTER] Any final thoughts
for everyone watching? IRENE ZANON: I was very
excited to present this. Don't hesitate to reach out if you
have any questions, or any feedback, or any requests. We are more than happy to just
provide more stuff for you. And I also want to point out that
this work is not only my work. It is a collaborative work. And there are also other
colleagues in the Fortnite UX UI team that have contributed
to some of these functions. And they are also
credited in the functions. So huge thanks to everyone. I'm really happy that we came to this
day, and that I was able to show it. Thank you a lot,
Pavlo, for being here. It was really important
to me that you were here. And thanks a lot to Adrienne Pugh,
because she provided lots of support for the material lab. To Matthew Watson, because he helped
with getting it to the Marketplace. To you, and then for the
coordinating Livestream, of course, you, Tina, I meant. And then, and the entire
Fortnite UX UI team. TINA WISDOM: Absolutely. And thank you both for taking
the time to be here today. I know you're not unbusy people. [LAUGHS] So I appreciate you
being here and taking the time to sit down with us, and
walk through the project, and really give everyone an
in-depth look at how this works, and how they can utilize it,
and what these nodes are, where they can find them. So thank you so much for
taking the time to do that. I really appreciate it. IRENE ZANON: It was a pleasure. TINA WISDOM: Awesome. And then, last but
certainly not least, thank you, everyone, who came
and watched the show today. If you missed any part of
the stream, no worries. We post everything in video format. That can be viewed on demand on
both our Twitch and YouTube channels at Unreal Engine. You can also follow us on all
social media Unreal Engine. As well as, please, come
say hi in the forums, where you can get all the latest
news as well as find other like-minded individuals
and developers who can help you along your development
journey answer any questions. Or you might be able to
help someone else as well. So come join us there as well. And with that, one last big
thank you for everyone who came. And we'll see you all tomorrow. We have another episode
of LFG tomorrow. We'll have on some of the developers
who created the award-winning VR game Moss 2. So make sure you come check that out. And, yeah, we'll see you all later. Bye, everyone. IRENE ZANON: Bye-bye. [AUDIO LOGO]