Lighting takes too much memory

Coordinator
Mar 4, 2011 at 4:32 AM

When I try to push the engine to its limits, by drawing 25*25 regions of 16*16*128 blocks, i get an outofmemory caused by the lighting queue.

The problem is in Ligthting.cs, the line :

LightRegion(0, WorldSettings.MAPWIDTH, 0, WorldSettings.MAPLENGTH);

 When i remove this line , i can render this big world with acceptable FPS on the intel laptop, but the lighting is off. Then i can light regions one by one by adding a block !

I tried to mess with lighting.cs without much success to simulate adding a block in each region, replacing this line with

  for (int y = WorldSettings.MAPHEIGHT - WorldSettings.REGIONHEIGHT/2; y > -1; y -= WorldSettings.REGIONHEIGHT)
            {
                for (int x = WorldSettings.REGIONWIDTH / 2; x < WorldSettings.MAPWIDTH; x += WorldSettings.REGIONWIDTH)
                {
                    for (int z = WorldSettings.REGIONLENGTH / 2; z < WorldSettings.MAPLENGTH; z += WorldSettings.REGIONLENGTH)
                    {
                        BlockAdded(BlockType.Dirt, x, y, z);
                    }
                }
            }
The world gets only partially lighted.

Any ideas ? At least there may be a way to process only the regions over the ground. 


Coordinator
Mar 4, 2011 at 5:25 PM

The lighting is fairly buggy to be honest - i never managed to get it to work completely correctly. If you place and remove multiple light blocks in an areas you can get the wrong lighting.

Looking at the code again the LightRegion method which sets up the initial region lighting is definately the culprit. Basically it is queing EVERY block above ground in the region to be processed for lighting....

                        if (!inShadow)
                        {
                            _lighting[x, y, z] = WorldSettings.MAXLIGHT;
                            toLight.Enqueue(new Light(x, y, z, WorldSettings.MAXLIGHT));
                        }

The reason for this is to allow the light to fill into areas which are in shadow from the direct overhead 'sun' lighting. The problem is that it's not a very smart algorithm but i'm stumped at the moment as to how it could be improved.

The inShadow check should prevent it lighting areas below ground so that shouldn't be a problem.

The only thing i can think of at the moment is that it could be a 2 stage process so you light for sun

So in the first pass....
                        if (!inShadow)
                        {
                            _lighting[x, y, z] = WorldSettings.MAXLIGHT;
			    //Only do direct SUN lighting.
                            //toLight.Enqueue(new Light(x, y, z, WorldSettings.MAXLIGHT));
                        }
Then repeat the process loop but only queue blocks which have unlit neighbours
Second pass...
                        if (!inShadow)
                        {
				if (hasUnlitNeighbours(x,y,z)) {
                            		toLight.Enqueue(new Light(x, y, z, WorldSettings.MAXLIGHT));
				}
                        }
Obviously since this requires 2 passes it is going to be slower, but since this function is only called once when the region is initialized it shouldn't
have too much of an impact.


 

 

 

 

Coordinator
Mar 7, 2011 at 3:34 AM

Yes it works better, by doing this and changing _lightheight from int to byte I was able to render 37*37 regions of 16*16*128 without filling the memory.

I get 4FPS on the laptop when looking at the whole world, but on the desktop with a geforce 9800GT it still runs fine.

 I think won't commit it because it's really marginal cases, we will surely have to redo the lighting when we will display a dynamic set of regions.

Something i saw when pushing the engine like this is that there seems to be no occlusion culling, fps is still very bad when looking at the world from inside a valley,

we re still drawing the whole regions hidden behind the cliff.