Skip to content

Instantly share code, notes, and snippets.

@Ethan-Bierlein
Last active August 16, 2016 20:09
Show Gist options
  • Save Ethan-Bierlein/0c42c2313bf3d747c642fc994b9fa8a6 to your computer and use it in GitHub Desktop.
Save Ethan-Bierlein/0c42c2313bf3d747c642fc994b9fa8a6 to your computer and use it in GitHub Desktop.
Voxel Lighting Algorithm
/// <summary>
/// Generate lighting for an individual voxel.
/// </summary>
/// <param name="x">The x coordinate of the voxel.</param>
/// <param name="y">The y coordinate of the voxel.</param>
/// <param name="z">The y coordinate of the voxel.</param>
public void GenerateIndividualVoxelLighting(int x, int y, int z)
{
Voxel currentVoxel = this.FetchVoxel(x, y, z);
Voxel currentVoxelUp = this.FetchVoxel(x, y + 1, z);
Voxel currentVoxelNorth = this.FetchVoxel(x, y, z + 1);
Voxel currentVoxelSouth = this.FetchVoxel(x, y, z - 1);
Voxel currentVoxelEast = this.FetchVoxel(x + 1, y, z);
Voxel currentVoxelWest = this.FetchVoxel(x - 1, y, z);
byte maxLightingValue = new byte[]
{
currentVoxelUp.Lighting,
currentVoxelNorth.Lighting,
currentVoxelSouth.Lighting,
currentVoxelEast.Lighting,
currentVoxelWest.Lighting
}.Max();
if(maxLightingValue == currentVoxelUp.Lighting)
{
currentVoxel.Lighting = maxLightingValue;
this.SetVoxel(currentVoxel, x, y, z);
}
else
{
currentVoxel.Lighting = (byte)MathHelper.Clamp(maxLightingValue - 1, Voxel.MIN_LIGHTING, Voxel.MAX_LIGHTING);
this.SetVoxel(currentVoxel, x, y, z);
}
}
/// <summary>
/// Generate the appropriate lighting for each voxel based on the voxel
/// data itself as a whole.
/// </summary>
public void GenerateVoxelLighting()
{
// Fill the top layer of voxels with full lighting values, regardless
// of each voxel's solidity.
for(int x = 0; x < this.Width; x++)
{
for(int z = 0; z < this.Depth; z++)
{
Voxel currentVoxel = this.FetchVoxel(x, this.Height - 1, z);
currentVoxel.Lighting = 16;
this.SetVoxel(currentVoxel, x, this.Height - 1, z);
}
}
// Iterate over each layer downwards and determine the lighting of each
// voxel based on it's neighbors.
for(int y = this.Height - 1; y >= 0; y--)
{
// Perform the first sunlight pass in the positive and negative
// horizontal X/Z directions and calculate the lighting values
// for each voxel.
for(
int xa = 0, xb = this.Width - 1;
xa < this.Width && xb >= 0;
xa++, xb--
)
{
for(
int za = 0, zb = this.Depth - 1;
za < this.Depth && zb >= 0;
za++, zb--
)
{
this.GenerateIndividualVoxelLighting(xa, y, za);
this.GenerateIndividualVoxelLighting(xb, y, zb);
}
}
// Perform a final horizontal pass in the X/Z direction and determine if a
// voxel is completely surrounded by non-transparent voxels. If so, then set
// the lighting of that voxel to zero.
for(int x = 0; x < this.Width; x++)
{
for(int z = 0; z < this.Depth; z++)
{
Voxel currentVoxel = this.FetchVoxel(x, y, z);
Voxel currentVoxelNorth = this.FetchVoxel(x, y, z + 1);
Voxel currentVoxelSouth = this.FetchVoxel(x, y, z - 1);
Voxel currentVoxelEast = this.FetchVoxel(x + 1, y, z);
Voxel currentVoxelWest = this.FetchVoxel(x - 1, y, z);
Voxel currentVoxelUp = this.FetchVoxel(x, y + 1, z);
Voxel currentVoxelDown = this.FetchVoxel(x, y - 1, z);
if(
currentVoxelNorth.Transparency == 16 &&
currentVoxelSouth.Transparency == 16 &&
currentVoxelEast.Transparency == 16 &&
currentVoxelWest.Transparency == 16 &&
currentVoxelUp.Transparency == 16 &&
currentVoxelDown.Transparency == 16
)
{
currentVoxel.Lighting = 3;
this.SetVoxel(currentVoxel, x, y, z);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment