I am creating a Minecraft-like terrain engine in XNA to learn HLSL and more XNA. The problem is my lighting algorithm. Whenever a block which emits light is placed, it takes about half a second to calculate it. I have implemented the lighting in a recursive way.
public void DoLight(int x, int y, int z, float light)
{
Vector3i xDecreasing = new Vector3i(x - 1, y, z);
Vector3i xIncreasing = new Vector3i(x + 1, y, z);
Vector3i yDecreasing = new Vector3i(x, y - 1, z);
Vector3i yIncreasing = new Vector3i(x, y + 1, z);
Vector3i zDecreasing = new Vector3i(x, y, z - 1);
Vector3i zIncreasing = new Vector3i(x, y, z + 1);
if (light > 0)
{
light--;
world.SetLight(x, y, z, (int)light);
Blocks.Add(new Vector3(x, y, z));
if (world.GetLight(yDecreasing.X, yDecreasing.Y, yDecreasing.Z) < light &&
!world.GetBlock(yDecreasing.X, yDecreasing.Y, yDecreasing.Z).IsSolid &&
world.InBounds(yDecreasing.X, yDecreasing.Y, yDecreasing.Z))
DoLight(x, y - 1, z, light);
if (world.GetLight(yIncreasing.X, yIncreasing.Y, yIncreasing.Z) < light &&
!world.GetBlock(yIncreasing.X, yIncreasing.Y, yIncreasing.Z).IsSolid &&
world.InBounds(yIncreasing.X, yIncreasing.Y, yIncreasing.Z))
DoLight(x, y + 1, z, light);
if (world.GetLight(xDecreasing.X, xDecreasing.Y, xDecreasing.Z) < light &&
!world.GetBlock(xDecreasing.X, xDecreasing.Y, xDecreasing.Z).IsSolid &&
world.InBounds(xDecreasing.X, xDecreasing.Y, xDecreasing.Z))
DoLight(x - 1, y, z, light);
if (world.GetLight(xIncreasing.X, xIncreasing.Y, xIncreasing.Z) < light &&
!world.GetBlock(xIncreasing.X, xIncreasing.Y, xIncreasing.Z).IsSolid &&
world.InBounds(xIncreasing.X, xIncreasing.Y, xIncreasing.Z))
DoLight(x + 1, y, z, light);
if (world.GetLight(zDecreasing.X, zDecreasing.Y, zDecreasing.Z) < light &&
!world.GetBlock(zDecreasing.X, zDecreasing.Y, zDecreasing.Z).IsSolid &&
world.InBounds(yDecreasing.X, yDecreasing.Y, zDecreasing.Z))
DoLight(x, y, z - 1, light);
if (world.GetLight(zIncreasing.X, zIncreasing.Y, zIncreasing.Z) < light &&
!world.GetBlock(zIncreasing.X, zIncreasing.Y, zIncreasing.Z).IsSolid &&
world.InBounds(zIncreasing.X, zIncreasing.Y, zIncreasing.Z))
DoLight(x, y, z + 1, light);
}
}
Does anyone see what is costing me so much performance? And if so, could you please suggest any way to fix it?
Especially when I try to update only a single light every frame, I get a depressingly low FPS of 4 (maybe the recursion is the problem). Does anyone know if a iterative would increase performance ? If so, how would I implement it?