private static void FluidFillSunLight(Chunk chunk) { for (byte x = 0; x < Chunk.WidthInBlocks; x++) { for (byte z = 0; z < Chunk.LengthInBlocks; z++) { int offset = BlockStorage.BlockIndexByRelativePosition(chunk, x, z); for (byte y = Chunk.MaxHeightIndexInBlocks; y > 0; y--) { var blockIndex = offset + y; if (BlockStorage.Blocks[blockIndex].Type != BlockType.None) // solid blocks can't propagate light. { continue; } var blockLight = BlockStorage.Blocks[blockIndex].Sun; if (blockLight <= 1) // if block's light value is too low (dark), { continue; // just skip it. } var propagatedLight = (byte)((blockLight * 9) / 10); PropagateSunLight(blockIndex + BlockStorage.XStep, propagatedLight); // propagate light to block in east. PropagateSunLight(blockIndex - BlockStorage.XStep, propagatedLight); // propagate light to block in west. PropagateSunLight(blockIndex + BlockStorage.ZStep, propagatedLight); // propagate light to block in north. PropagateSunLight(blockIndex - BlockStorage.ZStep, propagatedLight); // propagate light to block in south. // DO NOT repropagete to upper block which we don't need to do so and may cause loops! PropagateSunLight(blockIndex - 1, propagatedLight); // propagate light to block down. } } } }
/// <summary> /// Clears all lighting and then applies sun-lighting. /// </summary> /// <param name="chunk"></param> private static void SetInitialLighting(Chunk chunk) { byte sunValue = Chunk.MaxSunValue; for (byte x = 0; x < Chunk.WidthInBlocks; x++) { for (byte z = 0; z < Chunk.LengthInBlocks; z++) { int offset = BlockStorage.BlockIndexByRelativePosition(chunk, x, z); bool inShade = false; // if we get direct sunlight, inShade will be set to false. for (byte y = Chunk.MaxHeightIndexInBlocks; y > 0; y--) { if (!inShade && BlockStorage.Blocks[offset + y].Type != BlockType.None) // if we're under direct sunlight and just hit a solid block. { inShade = true; // set inShade to true; } BlockStorage.Blocks[offset + y].Sun = inShade ? (byte)0 : sunValue; BlockStorage.Blocks[offset + y].R = 0; BlockStorage.Blocks[offset + y].G = 0; BlockStorage.Blocks[offset + y].B = 0; } } } }
/// <summary> /// Builds vertex list for chunk. /// </summary> /// <param name="chunk"></param> private void BuildVertexList(Chunk chunk) { if (chunk.Disposed) { return; } Clear(chunk); for (byte x = 0; x < Chunk.WidthInBlocks; x++) { for (byte z = 0; z < Chunk.LenghtInBlocks; z++) { int offset = BlockStorage.BlockIndexByRelativePosition(chunk, x, z); for (byte y = chunk.LowestEmptyBlockOffset; y < chunk.HighestSolidBlockOffset; y++) { var blockIndex = offset + y; var block = BlockStorage.Blocks[blockIndex]; if (block.Type == BlockType.None) { continue; } var position = new Vector3Int(chunk.WorldPosition.X + x, y, chunk.WorldPosition.Z + z); this.BuildBlockVertices(chunk, blockIndex, position); } } } var vertices = chunk.VertexList.ToArray(); var indices = chunk.IndexList.ToArray(); if (vertices.Length == 0 || indices.Length == 0) { return; } chunk.VertexBuffer = new VertexBuffer(this.Game.GraphicsDevice, typeof(BlockVertex), vertices.Length, BufferUsage.WriteOnly); chunk.VertexBuffer.SetData(vertices); chunk.IndexBuffer = new IndexBuffer(this.Game.GraphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly); chunk.IndexBuffer.SetData(indices); }