Sign in to follow this  
Haytil

How to do Loading Screens

Recommended Posts

Hi, I was wondering how developers create loading screens. The only sensible way I can think of is if data is loaded in small, discrete chunks. However, the chunks would have to be able to be loaded in 1/60th of a second, so that the program can go through the render loop and present the loading screen at a good framerate. In other words, the first character's data would be loaded, the loading animation would render a frame, then the first character's data will be manipulated to suit the current level, then another frame is rendered, then the second character's data is loaded, etc. But this seems like a real pain, breaking up your data into such small pieces. Is there another way to do it? Thanks. -Gauvir_Mucca

Share this post


Link to post
Share on other sites
I'ld create another thread which were loading the data. Then when it's done loading it'ld set a bool variable to true and close itself, and when the first(rendering) thread sees that this flag has been set it'll go on to the menu screen(or whatever you need after the loading screen).

Share this post


Link to post
Share on other sites
Firstly have you ever seen a loading screen with smooth refresh? I haven't. Every load screen I know of (ok not every, but 95% of them anyway) jitter up in huge jumps and don't really give you any acurate feedback. BF1942 had a habbit of getting 95% complete in 5 seconds then sitting there for another 3 mins doing nothing in particular, and I think it was Tribes Vengance did the opposite - it would get to about 50% really slowly then suddenly finished. If you get something like fraps which tells you the framerate you'll see that most of them are only redrawn once or twice a second if that.

All you really need todo is update the loading screen after each mesh/texture rather than cutting them up. And even then you can probably get away with loading batches at a time. The loading screen is really just a nice way to say "Hey this program hasn't crashed - just wait a sec", so the accuracy isn't that important. Personally I just have a big list of models I want to load, then after each load I update the loading screen then move onto the next one. Its not smooth because each model takes a different amount of time to load (health pickup is almost instant where as the level mesh is a few seconds) but nobody has every complained or even noticed :D

Share this post


Link to post
Share on other sites
The loading system I saw for PS2 (where you can't do threads) basically did what the AP suggested. Each loadable item was split into small chunks. Then an OO-version would be:

class LoadableObject
{
StartLoad();
ContinueLoad();
EndLoad();
}
So the first method did the initilisation, then ContinueLoad would load a small amount of data and finally EndLoad did any tidying.

I actually use a loading thread. By using Sleep(time) I can set the max fps for the load-screen rendering to optimise time sepnt actually loading the data. It works very well.

Share this post


Link to post
Share on other sites
Quote:
Original post by d000hg
The loading system I saw for PS2 (where you can't do threads) basically did what the AP suggested. Each loadable item was split into small chunks.


The actual data itself wasn't split into seperate files though (which I think was what the AP wasn't happy with). You just load your one mesh file till either its finished or you've reached your time limit then just pause while loading screen updates then continue loading. So your while loop might looke something like:


while ((pos < fsize) && (time < MAX_LOAD_TIME))
{
... loading code ...
}

// if we've finished loading say so
if (pos >= fsize)
return 1;
else if (time >= MAX_LOAD_TIME)
return 0; // still need more loading
else
return -1; // error or something


so you just keep calling this while rendering the loading screen every time it returns. When you get 1 you move onto your next model till your done. Personally I havent' bothered, but if your loading very large files (which I'm not) then its definatly a good option and much simpler than a second thread.

Share this post


Link to post
Share on other sites
To have it load smoothly, you're going to have to split the process into two different threads. One thread would be responsible for loading the data and outputing the status of what it's loading while the other would be responsible for displaying the status of the background process. If you have access to the .NET framework, you'll be using the System.Threading namespace.

Share this post


Link to post
Share on other sites
As already said - you don't need threads for this. But it's prabably easier to use them then rewrite how every different file type is loaded. Because the jobs of the two threads don't need to be related at all, you can escape all the nasty side of multithreaded programming.

Share this post


Link to post
Share on other sites
From a UI feedback point of view, I think I would argue that a jerky progress meter is actually BETTER than a very smooth one, particularly with long loads (e.g. 20+ seconds). No progress meters are ever continuous, and by now users have been conditioned to expect the jumping. Furthermore, they can hear the hard drive clicking away, and when the progress bar is tied to that clicking it provides a level of reinforcement (yes, this is really doing something, please be patient) that a calmly scrolling bar in the face of intermittent HD activitiy does not have.

It is a problem when games decide that they will assign each file a percentage of the progress bar (20 files, so each one is 5% right?), then load 95% of them in 4% of the time and sit there for 30 seconds without changing. I think it's important to identify which files take longer to load (file size alone may be enough) and assign them larger percentages. It's also important to make sure that the progress bar is never still for more than 5-10 seconds, to reassure people that nothing has frozen.

I've seen some programs (compression and installation programs, for example) that actually use two progress bars - one for the "total progress," and one for the processing of the current file after it's been loaded into memory (like when the program is creating a BSP or unencrypting or whatever). I always thought that that was a particularly effictive bit of UI.

Share this post


Link to post
Share on other sites
Quote:
Original post by d000hg
Because the jobs of the two threads don't need to be related at all


Actually they do definatly need to be linked. How do you know what percentage to display if they aren't related at all? Thats also a problem in general that sometimes different things will load at different speeds on different machines. The first time you load a level the IO might be slowest, but then next time its already cached so the IO is pretty quick and its the BSP creator thats slower. So if you've said 50% is IO and 50% is bsp creation then on two different runs of your program the meter will move differently (first time 1st half will be slower, 2nd time 2nd half will be slower). You'll never be able to acuratly say how much of the loading is complete - a good guess is all you have which is why I've never bothered to split up loading into chunks or create another thread. Even if I do all that I still have to just 'best guess' at how much time each section takes so I don't thing you gain anything.

Share this post


Link to post
Share on other sites
I use threads, and while it can be tricky, I think it is worth it, because if you ever decide you want to stream data in without a loading screen, you can. This is useful to have large continuous worlds without breaking it up every few steps to load the next area. Also, nobody says you really need a percent done indicator on your loading screen. A lot of games don't have them, and really, all you need is some animation to show the program hasn't crashed.

tj963

Share this post


Link to post
Share on other sites
Well can you use a singleton object that handles the menu loading and refreshing?

So inside your loading loop you update your loading bar by calling the singleton object. This method works best if you have a single progress bar and a total progress bar.

I have never done threads (haha I need to start learning lol) but I would think using two threads is the best way to go.


Share this post


Link to post
Share on other sites
Quote:
Original post by Vern777
Well can you use a singleton object that handles the menu loading and refreshing?


Why a singleton? A normal object works just as well (IMHO: alot better), there is absolutely nothing that the singleton will solve in this matter. The problem is to know how much you've loaded and how much is left, as well as render every once in a while.

I think that threads are the way to go if you need max fps update on the loading bar, just poll the loading thread on how far it's gotten every time you render. A more "jumping" loading bar animation could be done while loading. Just render after each loaded object. Heck, you can even use that to get the filename before loading so you can have "Loading: SingletonsOhTehNoes.omg..." etc.

What I can't really figure out is, how do you know how much is left? Do you insert some extra info in the beginning of the main load file or do you go through the list of all things that need to be loaded, or how do you guys do it?

Share this post


Link to post
Share on other sites
I posted without much thinking.

But my idea is that you may have different loading code so you can call the singleton object from anywhere. But usually all your loading code belong in the same place...

So you have a loop, you know how many times to loop perhaps, or you know how many vertices you need to load, that would figure into you percentage equation...





Share this post


Link to post
Share on other sites
Rant! hehe I made it small so you can ignore it:
The singleton is the most misunderstood and missused pattern of all, it has become a "argh I'm to tired to design, let's just make this work!" pattern suddenly. It holds no advantage over being passed around like any other object you need to use. Unless you're force fitting it into something who's architecture / interface you can't / don't want to affect to much. Thus sneaking in a black-box communication system that there is no indication of that's it being used. To give an example of what I mean:

scene.load( filename ); VS scene.load( filename, loadingBar );

Which one uses the singleton (i.e. which one doesn't hint about using a loading bar?) and which one shows not just to the caller but the implementor of scene.load() that there's a loading bar and it should be used?


I've been thinking about "how do you know how big a step is?". Clearly there are differences in loading times, even for the same object made twice in a row or on two different computers (as pointed out by other posters). So there isn't even a point trying to make one object "worth more" than another. But if we (say 3D game) count triangles or models, when saving the game map this data is saved in a header part (i.e. in the beginning). Then you'd know how much to step after each modell. Other resources like sound and textures has to be taken into account too, of course. Easiest might just be having a "Total resources: 432" in the beginning and a small texture counts as much as a complex model. As mentioned earlier, we've almost come to expect jerky loading bars :)

I'm just speculating here. Has anyone tried this approach?

Share this post


Link to post
Share on other sites
Here is one approach you can try to make a smooth progress bar.

You need to know a few things about the machine that your app is running on:
1. The amount of data that you are going to be loading, in bytes for example
2. The spead at which your machine is loading that data (eg. bytes per millisecond)
3. A timer source (eg. in milliseconds)

The gist of this is to do an animation of the progress bar by calculating, on the fly, the spead at which the data is loading.

You can load the first chunk of data and figure out how long it took, and how many bytes were loaded. From this you can calculate the spead (bytes per millisecond, or what ever units you like).

Now that you know the spead at which your data is loading, you can do two things. If you assume that the rest of the data will load with a similar speed, then you can use the calculated spead to animate the progress bar. If not, then you can redo this calculation after each chunk of data is loaded.

To animate the progress bar, you smoothly interpolate it based on how much calculated time is left to load the remainder of the data.

If the platform that you are running your app on blocks during disk IO then you can either take the approach of using theads, or you can try to load data a byte or a few bytes at a time, do your progress bar calculations, and then continue on in a loop. If you write some library routines for doing your disk IO, then try incorporating this sort of progress bar functionality, and perhaps make it configurable for the times when you don't want the overhead of this kind of functionality.


Terry

Share this post


Link to post
Share on other sites
Quote:
Original post by Seriema
Rant! hehe I made it small so you can ignore it:
The singleton is the most misunderstood and missused pattern of all, it has become a "argh I'm to tired to design, let's just make this work!" pattern suddenly. It holds no advantage over being passed around like any other object you need to use. Unless you're force fitting it into something who's architecture / interface you can't / don't want to affect to much. Thus sneaking in a black-box communication system that there is no indication of that's it being used. To give an example of what I mean:

scene.load( filename ); VS scene.load( filename, loadingBar );

Which one uses the singleton (i.e. which one doesn't hint about using a loading bar?) and which one shows not just to the caller but the implementor of scene.load() that there's a loading bar and it should be used?


I've been thinking about "how do you know how big a step is?". Clearly there are differences in loading times, even for the same object made twice in a row or on two different computers (as pointed out by other posters). So there isn't even a point trying to make one object "worth more" than another. But if we (say 3D game) count triangles or models, when saving the game map this data is saved in a header part (i.e. in the beginning). Then you'd know how much to step after each modell. Other resources like sound and textures has to be taken into account too, of course. Easiest might just be having a "Total resources: 432" in the beginning and a small texture counts as much as a complex model. As mentioned earlier, we've almost come to expect jerky loading bars :)

I'm just speculating here. Has anyone tried this approach?


That's not what I meant.

What I wanted to do is to have a loading screen singleton... This has nothing to do with the actual loading.

If you have to refresh your screen while loading you need someway to refresh from inside you loading code. That's why it's best to use threads.

So at the beginning of loading some stuff I would do:

LoadScreen::getSingletonPtr()->start(totalNumOfItems);

for(int i = 0; i < totalNumOfItems; i++)
{

LoadScreen::getSingletonPtr()->setCurrentItem(i);
load(resource);


}


load(RESOURCE res)
{

//figure out how much each loop is worth in the total progress
//of this item pertange while. So if you have 100 vertes, 1 vert would
//be 1 % on the progress bar
LoadScreen::getSingletonPtr()->calPercentage();
for(int i = 0; i < numOfVerts; i++)
{

//load some verts
LoadScreen::getSingletonPtr()->updateCurrentItem(); //updates progress bar

}

}


Share this post


Link to post
Share on other sites
just doing loadResource is trival..

What if I want to traverse a tree and update the progress of my tree traversal I would so something similar maybe.

I'm in no way an expert...

Share this post


Link to post
Share on other sites
My prefered method is just to total up all the media im loading, then work out what each one is in terms of percetage. Pretty easy to do this with code to give it some dynamic quality. Then just load the files one by one, and update the Loader.Percent attribute of the loader class each time a file is loaded... then when the screen refreshes i.e.: Loader.Render() is called from your main loop, then it draws a nice up-to-date loading bar... so what if its jerky... if your loading more than 100 files, you'll prolly get a fairly even spread and then no one is gonna notice anyways ;-)

Hope this helps.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The other thing is that you don't have to do a percentage loaded kind of thing :- for example I have a suspicion that Quake doesn't do that. All the user is really interested in is that his computer hasn't crashed and that it is doing something normal (eg think of the busy cursor in most OS's [usually a sand timer]). For instance you can have an animation of some sort (say a spining hard-disk), and whilst you do that you can add messages about what you're doing ("Loading map...", "Loading textures...", "Loading models...", "Loading sounds..." etc.) [this incidentally gives you a bit of feedback when the user says 'it crashes in the load screen, blah blah blah']

Share this post


Link to post
Share on other sites
The singleton pattern does not fit this problem-space well. In order to use a singleton the object:

a) Needs to enforce a single instance.
b) Needs to have global access from the full program.

I would never use a singleton for this problem because it doesn't satisfy the two requirements to use the pattern... it actually doesn't satisfy either of them.

Share this post


Link to post
Share on other sites
I’ve have to admit that I have never been exposed too the problem, but what I’ve would have done was having one thread for actual IO reading, one thread for decoding resources, and one thread (the main one) for doing Graphics. The reason for the layout is that I use OpenGL which is not multithreaded. Therefore the graphics thread will at start initialize the decoding thread which initializes the IO thread. Then the IO thread reads in work to done from a queue and after reading the file into memory, adds it to another queue ready for decoding. When the decoding thread notices this it decodes the resource and if it’s some kind of script adds more resources to load to the IO thread. Since graphics objects in my case needs to be loaded in OpenGL from the same thread as rendering the main thread will wait for textures/models to be loaded and load them as needed. If a set amount of time has passed it update the progress bar. The progress bar will then be a percentage of total objects loaded / total objects processed by the IO thread.
It won’t be a linear progress bar but it will be accurate which is more important.
Another bonus is as multi core processors is coming the loading and decoding of data can be very efficient. Since I’m also using .Net the threading support should be sufficient for this layout I hope. But I may also be over my head here.

My to cents.

Jarle

Share this post


Link to post
Share on other sites
Okay, but how do I update the progress bar from abitrary loading functions??? I want to embed loading progress bar from anywhere...

Why would a loading MENU singleton not fit global access of loading menu?

Share this post


Link to post
Share on other sites
Although the idea of a background loading thread is quite cool, and probably a good way, properly optimized, to eliminate loading screens as much as possible, if you want to avoid using multiple threads, I'd recommend using coroutines.

You can either make a load loop that displays a loading screen, consistently updated, or you could probably even work it into your main loop and do "background" loading.

Share this post


Link to post
Share on other sites
Quote:
Original post by kaysik
Quote:
Original post by d000hg
Because the jobs of the two threads don't need to be related at all


Actually they do definatly need to be linked. How do you know what percentage to display if they aren't related at all? Thats also a problem in general that sometimes different things will load at different speeds on different machines. The first time you load a level the IO might be slowest, but then next time its already cached so the IO is pretty quick and its the BSP creator thats slower. So if you've said 50% is IO and 50% is bsp creation then on two different runs of your program the meter will move differently (first time 1st half will be slower, 2nd time 2nd half will be slower). You'll never be able to acuratly say how much of the loading is complete - a good guess is all you have which is why I've never bothered to split up loading into chunks or create another thread. Even if I do all that I still have to just 'best guess' at how much time each section takes so I don't thing you gain anything.
I don't show a % complete, I just show a repeating animation (a bit like on the KnightRider car) to show something is happening. But even if I did, it's not much data overlap and probably not the kind which can cause problems. Either way it's simple as multithreaded applications go!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this