Last active
August 16, 2016 20:09
-
-
Save Ethan-Bierlein/0c42c2313bf3d747c642fc994b9fa8a6 to your computer and use it in GitHub Desktop.
Voxel Lighting Algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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