Intuitive Material Building with the UI Material Lab | Inside Unreal

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[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]
Info
Channel: Unreal Engine
Views: 53,300
Rating: undefined out of 5
Keywords: Unreal Engine, Epic Games, UE4, Unreal, Game Engine, Game Dev, Game Development
Id: WaHlhkmVDoI
Channel Id: undefined
Length: 124min 5sec (7445 seconds)
Published: Thu Apr 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.