Hi, I'm Jon Moore, I'm a graphics engineer, Iron Galaxy Studios and today we're talking about Optimization in 3D Video Games. The idea being this will just be a quick introduction to get you pointed in the right direction. It's actually a topic that can take hours, days, years to really delve into all of the details of different ways you can make modern software run fast. And the motivation here is that engine programmers might spend more than half of their time working on optimizing a video game. Because it's very important when you work on video game consoles that you're able to do this. Or else your video games from year to year are never going to look any better, because the hardware's not going to get better. You will make your game run faster in order to keep pushing the limits of what you can do. Your artists are going to want to render more trees, more characters, more explosions, whatever the case might be. If you want more content, you need Bill to do it. And the other reason I want to talk about it is that I've seen young developers struggle with it in the past. It would be difficult to really start to wrap your head around this topic when you're first starting out. And the goal here is that you need your game to be able to run in 16.6 milliseconds for a 60 hertz game. Or 33.3 milliseconds for a 30 hertz game or 30 frames per second as the case may be. In order to be what's known as interactive frame rates. If you go lower than that, your players are going to start to notice the experience becomes choppy, it'll be harder to have the competitive game. If it's multiplayer, it's very important that you try to stay interactive frame times as often as possible. And before you get started with making your video game run faster, you need to do some things in preparation. The first one and possibly the most important, is that you needed to have performance counters that let you know if you're running slow. It can be difficult to tell right away if you have a problem and where the problem is. So being able to have a display that tells you how long it takes to run your video game for a given frame. Can let you hunt down, hey, this box fight is much slower than the rest of our game and we need to do something about it. And once you have slowdowns identified, you need to start taking more detailed captures with some more advanced tools. That you're probably not going to want content developer or a tester to work on. Go on and have an engineer take a look and say, hey animation, or physics or rendering, this is where our slowdown is. And we need a plan of attack to identify why we're spending half of our frame time working on this bottleneck. And the other important details you need to pick a minimum spec. If you spend all your time developing on a super high end PC and you actually want your game to run on a toaster. You're going to need to actually make sure that you spend time running the game on the toaster as often as possible. I've even professionally in the industry, there are cases where artists with a high powered machine will work on a very fancy effect. And not realize that, when you try to put it on a video game console, it's going to be much slower than the high end PC that they were developing on. It's very important to keep that in mind throughout development. And when we talk about optimizing, you need to think about life of a frame in a modern game engine. Typically a modern game has three frames of latency from the time when you press a button to the time where frame is actually rendered into a buffer and ready to be put onto the screen for the player to see it. Even though you might have three frames of work, they're all happening together at the exact same time and same overlap of 33 milliseconds, this is known as pipelining. So in the first frame, you usually receive your input from the player and you start processing your game logic. This'll be making your character jump and run around, follow paths, handle physics and collision detection. All the fun part of your game is going to happen there. Second frame, you'll have identified all of the logic of stuff moving around. And you've got a list of all of these things that you're going to need to draw. So your second frame is just going to be spent communicating those things to the graphics driver to pass off to the graphics card. So these would be things like setting up, hey, I want my player to draw and I want these textures on it. It needs to be these meshes and making all of that package together in a way that your graphics card, your discreet piece of hardware that handles your rendering can actually chew through them. And as the third frame is the GPU actually taking all those instructions and using its specialized hardware to render out the actual pixels the end user is going to see. And usually one of these three will be a limiting factor. But if one of these is running faster than the others and the other two are consistently your slowdown or maybe if it's just your GPU that's always slow. You don't actually need to worry about optimizing your others, because since everything's pipelined together. You don't want to waste time optimizing your game play logic, if actually you're always bound by rendering or vice versa. So I'm going to skip over talking about gameplay type issues. Because that's actually highly dependent on what you're actually making. And since I'm a rendering guy, I can actually share some details on dealing with rendering problems. So, your render frame, this is frame two, after you finish all of your gameplay logic, is usually limited by draw calls. This is happening in your CPU and it's the communication issue with the driver and you have two strategies for dealing with hitting your budget for draw calls. You need to draw faster or you need to draw less. And faster is a very difficult problem and that's usually what a professional engineer is going to be spending 20 hours a week working on. But when you're starting out, you need to focus on less. And this is still something that professional game developers do all the time. This is more focused on the content creators and it's much easier to get a grasp on when you're first starting out. So what do I mean by drawing less? So when you need your graphics card to draw something, it takes a list of triangles forming that geometry into a batch. And it needs to know a bunch of details about it that make it special. Is your character red? It needs a red texture attached and it needs different properties for the select shader to execute and make it look the way that it does. And they can be specialized in these different ways, but the more specialization you have, the more batches you're going to need. So the way you deal with this is you need to be able to reduce variation anywhere you don't need it. Do you need five different types of metal materials or can you just get away with one metal material? Can you atlas your textures together? So that way you have exactly the same resources being bound to different draws. When I say atlas, your crate is in the left part of the texture and maybe your torch is in the right part. And they're all shared in together in one texture resource that gets bound just once and then reused. When you have this reduction in specialization as I'm saying. Most modern game engines can intelligently merge batches of triangles together with common properties on the fly or offline. For example, Unity, a common game mentioned that you might be familiar with has static batching. Which intelligently merges, meshes with shared materials together. There's also a brute force method, that sometimes you might have to rely on especially if you're working in a more simpler framework of game engine. And you can just merge your meshes together by hand, making one giant triangle soup of a level that everything's jammed together into. Downside here is that your GPU's going to have to do more work, because you're pushing all of these triangles down it every frame. And you can't do anything to not render things that are behind the player anymore. Because it's just one giant mesh. So let's do a little bit about render issues, let's talk about the graphics card. So this is the third frame. And the most important thing is always start by looking for abnormally expensive costs here. Pretty good examples of this are, if you have an extremely over-tessellated piece of geometry. Like a tree or just a crate that for some reasons has tens of thousands of triangles. And you've got a bunch of them clumped together. That might be the cause of your slowdown is itself. And focusing on that one asset can be really critical to getting you into your frame time. Similarly watch for things like cinematic cameras that get turned on and then don't get disabled. So that way your game is actually invisibly rendering your video game multiple times over. And you didn't realize that's still happening. Another thing that I've actually seen happened professionally in development is artists trying to get fancy with specialized effects. And doing things like putting an expensive shader meant for rendering character skin. On every single blade of grass in the game, which is difficult when you need to render a meadow. But once you get through all of those kind of one-off hotspot issues, usually the most difficult thing that comes up all the time is lighting. And modern video game renders are usually either lighting through forward or deferred rendering. And when you're doing forward lighting, you typically have very limited light counts that you can handle dynamically. But you have overall lower overhead for your frame time. Deferred lighting is a strategy where the geometry gets processed separately from the lights. Which allows for you to get much higher light counts. Details of how these two methods actually work aren't super important, unless you really want to dig into engineering graphics programming. But understanding the differences between the pros and cons between them is very important when you're crafting a 3D video game. So with deferred lighting, one detail is that it only works on opaque objects. So that means that if you have tons of transparency in your scene that's lit. You're actually not getting a lot of benefit from deferred lighting. You might need to cut back on the amount of transparency or the number of lights in order to hit your frame budget. The other thing is it's very difficult to use with MSAA. Typically, people rely on some sort of post-processing method to handle that issue. But just know that anti-aliasing is an inherent problem in deferred rendering. And the high light also does not mean more shadowed lights. You can't just go crazy with the number of dynamic shadows in your game. This is an unsolved problem in modern game development. Maybe ten years from now it'll be possible, but not at the moment. Kind of the best use case for deferred is we've got an indoor scene with many small point or spot lights or torches or just point lighting throughout it. Don't take up a ton of pixels. They're all spread out. If that was a forward lit case, then you would have a problem. So forward lighting is where you're computing lighting directly when rendering a mesh. So, that's why the forward case is a problem. Is that if you have lights spread out all across a mesh, you're going to pay for those lights at every single pixel. The cost is the number of lights touching a mesh times the pixels the mesh is rendering to. And you can do some dicing to try and make it play better. So that way you have the mesh for the left side of your floor and the right side of your floor. But you might notice this circles back to the problem that I mentioned earlier where optimizing one case is making another case for us. We're going to increase CPU overhead by doing finer dicing. Another thing with forward lighting is that it works with transparency. Usually even deferred render is still going to forward lighting for transparency. But maybe you want to be fully forward just to make everything simpler. Best case for a fully forward game is where you've got a outdoor sunlit scene where you've got sunlight. Just one single light dominating the lighting for your art direction. And the number of smaller lights is minimal. So your actual light count can be quite low. Three or four might be all you need. Which actually brings me to another point, I was kind of mentioning transparency being a difficult case. It's actually inherently expensive due to what's known as overdraw. Where pixels are written to repeatedly, so you blend all of these layers together. This is especially problematic for particle effects. And is probably one of the things that you should most watch out for when you're trying to craft a boss fight or something or a special move for a character in your game. And you might notice that when you do a certain move or sequence in your game, it slows down when an explosion goes off. Dealing with those hot spots is often frequently related to transparency based effects that were being use there for that special case. And there's a couple different ways you can deal with this, try to simplify the materials on that transparency as much as possible. Does it even need to be dynamically lit? Does it need specular on it? Try to simplify that down. Another thing to do is you just visualize your overdraw and try to reduce overlap as much as possible. Here's an example of an overdraw visualization and you can see all of the bright spots. And the very dim boxes at the bottom are where there is only one layer of pixels being drawn to. But if you're rendering to those pixels towards the center of this [INAUDIBLE], dozens of times. It's dozens of repeated processing that you're doing compared to a normal frame, thus the cause for spikes. In conclusion, optimizing a modern video game, very difficult, but it's also a fun challenge that can be very rewarding. And the thing I like to think about is, the more you optimize your game, the more content that you can support in your game. Or the more complicated your game can be. And it's always excited to be empowering the content creators on your team, so that we can do bigger and better things.