{"id":11490,"date":"2011-05-04T07:06:15","date_gmt":"2011-05-04T12:06:15","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=11490"},"modified":"2011-05-04T07:46:59","modified_gmt":"2011-05-04T12:46:59","slug":"ask-me-a-question-loading-screens","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=11490","title":{"rendered":"Ask Me a Question: Loading Screens"},"content":{"rendered":"<p>In Earlier this week asterismW <a href=\"http:\/\/www.shamusyoung.com\/twentysidedtale\/?page_id=7305&#038;cpage=2#comment-206843\">asked<\/a>:<\/p>\n<p><br clear=\"all\"\/><\/p>\n<blockquote><p>I recently played Portal 2. Loved the game, but found the long\u00e2\u20ac&quot;and frequent\u00e2\u20ac&quot;loading screens irritating. In my mind, this should not be necessary for linear games. You are limited as to where you can go and what you can see, and you can only traverse the game in one direction. It seems like it would be easy to load an area, and once the player gets through it, have some sort of basic, dark corridor (or whatever) where not much is rendered. Then, while the player traverses the corridor, in the background the game can dump the last area and load the next one. Sure, the corridor will be boring, but surely it&#39;s better than staring at an immersion-killing loading screen. So, why is this not possible?<\/p><\/blockquote>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/loading2.jpg' class='insetimage' width='600' alt='Portal 2' title='Portal 2'\/><\/td><\/tr><\/table><\/p>\n<p>This is a subject near and dear to my heart, mostly because <em>streaming<\/em> content in an FPS is closely related to <em>procedural<\/em> content in an FPS.  That is, they have many of the same obstacles. But sticking to streaming content, asterismW is right that this is totally <em>possible<\/em>. It&#8217;s just <em>hard<\/em>.  <\/p>\n<p>Here is the production pipeline for most first-person games:<\/p>\n<p><!--more-->Level designer sets up the world, decides where the walls and floors go, places light sources, sets up the scripting (making characters talking and such) puts objects in the scene and generally makes some sort of playpen for the gamer. Then the designer runs some sort of pre-processing on a level to prepare it for use.  A program will analyze the geometry of the level and work out what you can and can&#8217;t see from any given standpoint, so that the computer won&#8217;t waste its time drawing stuff you can&#8217;t see.  Without this, games would run unplayably slow. This usually takes a while, and in the end this program spits out an optimized level, ready for play. <\/p>\n<p>Another thing that is done during the pre-processing phase is to calculate the lights in the scene and work out where the shadows are.  One of the excellent things about iD Tech 4 (the Doom 3 engine) was that it could skip this last step.  No more fixed shadows, no more arduous lighting computations.  <\/p>\n<p>The pipeline varies a bit from engine to engine, but those are the basic steps.  Now let&#8217;s think about this and what would need to change to allow the game to stream in content without bringing the whole show to a halt for a loading screen.<\/p>\n<h3>Culling <\/h3>\n<p>At any given time, the game holds this map of what needs to be drawn when the scene is viewed from any given vantage point.  The problem is, it&#8217;s not that easy to just graft in a bunch of new geometry and have the game know what it should be drawing.  There would need to be some sort of system for analyzing THIS level and the NEXT level, and figuring out how to stitch them together.  This would be complicated to set up (but NOT insurmountable) and would add another step to level design.  Now when you want to test your level you need to run an additional program to connect it to the previous and following levels.<\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/loading4.jpg' class='insetimage' width='600' alt='Homefront' title='Homefront'\/><\/td><\/tr><\/table><\/p>\n<h3>Lighting<\/h3>\n<p>Currently the lighting calculations are slow and arduous and only done on one level at a time.  This means lights on the first level won&#8217;t shine into the second level and vice versa.  So, there will be this ugly seams where the levels join up.  Maybe there&#8217;s a shadow of a pillar on the door, but the shadow won&#8217;t go through the doorway.  This would look horrible.  Or maybe it would be be a lot brighter on one side of the door than the other. <\/p>\n<p>You would need to experiment to come up with the best technique to mitigate or hide this problem. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/loading1.jpg' class='insetimage' width='600' alt='Dead Space 2' title='Dead Space 2'\/><\/td><\/tr><\/table><\/p>\n<h3>Loading<\/h3>\n<p>At some point you need to start pulling in the data needed for the next level while the player is still busy in this one.  Suddenly your texture-loading code needs to be more robust.  You can&#8217;t just pull 100MB of texture data off of disk all at once (remember that we&#8217;re also talking about consoles, and that data might be coming off of a DVD, which is far slower than a hard drive) because it would cause a massive framerate hit.  Suddenly dropping down to two frames a second in the middle of a firefight (or in the case of Portal 2, in the middle of some aerial stunt) is <em>not<\/em> going to go over well with players. You have to gradually pull that stuff in and prepare it for use.  You need to throttle how much loading you do each frame, and preventing stuttering would take a lot of careful balancing.  <\/p>\n<div class=\"dmnotes\">Aside: You might be able to mitigate existing loading screens by looking for textures already in use.  In the process of fiddling around with level design in various engines (Unreal Engine, Source Engine) I notice that moving from one level to an <em>exact duplicate<\/em> of that same level takes about the same length of time as moving between completely unrelated levels.  I have this suspicion that most engines simply purge all texture data and load everything clean during a level change. Texture data is <em>huge<\/em>, and pulling it off of a hard drive (or worse, a DVD) is time consuming.  If the loading system had the ability to preview the texture manifest for the upcoming level and only purge what it wasn&#8217;t going to use, you might be able to vastly <em>shorten<\/em> loading screens without needing to invent some sort of streaming system.  <\/p>\n<p>However, this seems straightforward and I imagine <em>someone<\/em> would have done it by now if it was really this easy?<\/div>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/loading3.jpg' class='insetimage' width='600' alt='Crysis 2' title='Crysis 2'\/><\/td><\/tr><\/table><\/p>\n<h3>Transitioning<\/h3>\n<p>How do you handle level transitions?  When do you start loading the next area?  You need to do it soon enough that the data will be ready by the time the player reaches the door.  Again, you hit the problem of timing.  A PC with a SATA hard drive is going to be much faster than the DVD or Blu-Ray drive in your average console. What if the player runs towards the exit, triggers the load, and then backtracks for some reason?  Now you&#8217;ve potentially got the next level sitting in memory, unused, while the player goofs around on this one.  Is that possible? Do they both <em>fit<\/em> in memory? For them to both fit in memory, you need to set your per-level memory budget so that it never eats more than half of what you have to work with. Which means smaller levels.  Which means more frequent transitions. Which limits your level designs.  (It would be harder to pull off moments where you can look off into the distance and see where you were several encounters ago.  (Not that Portal 2 does this.))<\/p>\n<p>You can prevent the backtracking problem by having the player go through a one-way door, but that introduces a new problem.  The one-way door needs to be far enough away from the real end of the level that everything has time to load before they reach it. So you basically need a one-way door and a long hallway. (If you make it vast and interesting, you make it monstrously more difficult to stitch the levels together, so this transition area needs to be simple.) asterismW suggested as much in the original question, and it&#8217;s true that fifteen seconds of hallway is probably more interesting than fifteen seconds of loading screen. But since we&#8217;re also running the game while we&#8217;re loading, and the loading is being done in quick furtive actions, it&#8217;s going to take a lot longer than fifteen seconds.  So we&#8217;re comparing a fifteen second loading screen with (say) a fifty second hallway hike. You&#8217;ll end up with something like the elevators in the original Mass Effect. Going for a full minute without gameplay is likely to be just as flow-breaking as a loading screen.  Worse, actually: In five years the loading screens will be mitigated by improved hardware, but that fifty second walk will <em>always<\/em> take fifty seconds. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/loading5.jpg' class='insetimage' width='600' alt='Fallout: New Vegas' title='Fallout: New Vegas'\/><\/td><\/tr><\/table><\/p>\n<p>Having said all of this, I&#8217;m sure it&#8217;s <em>possible<\/em> to make a first-person game with no loading screens or obvious transition hallways.  (Although you might need an airlock now and again.)  I think the trick is that you would need to start over and build an engine around the idea of dynamic content, rather than kludging it in to the existing FPS engine paradigm. You&#8217;d need to engineer a more open-world engine. This would require different tools and a different production pipeline.  It would probably also require some small visual sacrifices.  (I can&#8217;t say what. I&#8217;m not up-to-date on where the performance bottlenecks are in the engines these days.) <\/p>\n<p>Programmers have a term for problems like this: <em>Nontrivial<\/em>.  The term is also used in <a href=\"http:\/\/en.wikipedia.org\/wiki\/Nontrivial\">mathematics<\/a>, but it has a special meaning in programming.  When a manager comes along and asks if you can do X, saying the problem is nontrivial is a way of saying, &#8220;Yes, I can do it.  It is physically possible, given enough hours.  However, it is so difficult or time-consuming that just explaining the parameters of the difficulties would bore you, and actually giving you a time estimate would offend you and cause you to accuse me of incompetence.&#8221;  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Earlier this week asterismW asked: I recently played Portal 2. Loved the game, but found the long\u00e2\u20ac&quot;and frequent\u00e2\u20ac&quot;loading screens irritating. In my mind, this should not be necessary for linear games. You are limited as to where you can go and what you can see, and you can only traverse the game in one [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-11490","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/11490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11490"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/11490\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}