/* * c02 c12 c22 * c01 c11 c21 * c00 c10 c20 */ public void CubeBlock(int x, int y, int z, TerrainManager terrain, Rect[] texCoord, Color ca, Color cb, Color cc, Color cd) { Chunk c11 = terrain.ChunkWithBlock(x, y, z); Chunk c21 = terrain.ChunkWithBlock(x + 1, y, z); Chunk c01 = terrain.ChunkWithBlock(x - 1, y, z); Chunk c12 = terrain.ChunkWithBlock(x, y, z + 1); Chunk c10 = terrain.ChunkWithBlock(x, y, z - 1); Chunk c02 = terrain.ChunkWithBlock(x - 1, y, z + 1); Chunk c22 = terrain.ChunkWithBlock(x + 1, y, z + 1); Chunk c00 = terrain.ChunkWithBlock(x - 1, y, z - 1); Chunk c20 = terrain.ChunkWithBlock(x + 1, y, z - 1); int x2 = x & Chunk.SIZE_X_MINUS_ONE; int z2 = z & Chunk.SIZE_Z_MINUS_ONE; // l is short for light // light intencity at a, b, c, d float la, lb, lc, ld; // sm stands for shadow mask float sm; Color gi; // cell face: x positive if (BlockManager.blocks[c21[(x + 1) & Chunk.SIZE_X_MINUS_ONE, y, z2].index].isTransparent) { la = CalculateLighting(c20[ClipX(x2 + 1), y, ClipZ(z2 - 1)].lightF, c20[ClipX(x2 + 1), y + 1, ClipZ(z2 - 1)].lightF, c21[ClipX(x2 + 1), y + 1, z2].lightF, c21[ClipX(x2 + 1), y, z2].lightF); lb = CalculateLighting(c21[ClipX(x2 + 1), y, z2].lightF, c21[ClipX(x2 + 1), y + 1, z2].lightF, c22[ClipX(x2 + 1), y + 1, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y, ClipZ(z2 + 1)].lightF); lc = CalculateLighting(c21[ClipX(x2 + 1), y - 1, z2].lightF, c21[ClipX(x2 + 1), y, z2].lightF, c22[ClipX(x2 + 1), y, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y - 1, ClipZ(z2 + 1)].lightF); ld = CalculateLighting(c20[ClipX(x2 + 1), y - 1, ClipZ(z2 - 1)].lightF, c20[ClipX(x2 + 1), y, ClipZ(z2 - 1)].lightF, c21[ClipX(x2 + 1), y, z2].lightF, c21[ClipX(x2 + 1), y - 1, z2].lightF); ShadedVerticeQuad(new Vector3(x2 + 1, y + 1, z2), new Vector3(x2 + 1, y + 1, z2 + 1), new Vector3(x2 + 1, y, z2 + 1), new Vector3(x2 + 1, y, z2), la, lb, lc, ld); TexQuad(texCoord[CellFace.Left]); sm = shadowMasks[CellFace.Left]; gi = GIs[CellFace.Left]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } // cell face: x negative if (BlockManager.blocks[c01[(x - 1) & Chunk.SIZE_X_MINUS_ONE, y, z2].index].isTransparent) { la = CalculateLighting(c01[ClipX(x2 - 1), y, z2].lightF, c01[ClipX(x2 - 1), y + 1, z2].lightF, c02[ClipX(x2 - 1), y + 1, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y, ClipZ(z2 + 1)].lightF); lb = CalculateLighting(c00[ClipX(x2 - 1), y, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y + 1, ClipZ(z2 - 1)].lightF, c01[ClipX(x2 - 1), y + 1, z2].lightF, c01[ClipX(x2 - 1), y, z2].lightF); lc = CalculateLighting(c00[ClipX(x2 - 1), y - 1, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y, ClipZ(z2 - 1)].lightF, c01[ClipX(x2 - 1), y, z2].lightF, c01[ClipX(x2 - 1), y - 1, z2].lightF); ld = CalculateLighting(c01[ClipX(x2 - 1), y - 1, z2].lightF, c01[ClipX(x2 - 1), y, z2].lightF, c02[ClipX(x2 - 1), y, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y - 1, ClipZ(z2 + 1)].lightF); ShadedVerticeQuad(new Vector3(x2, y + 1, z2 + 1), new Vector3(x2, y + 1, z2), new Vector3(x2, y, z2), new Vector3(x2, y, z2 + 1), la, lb, lc, ld); TexQuad(texCoord[CellFace.Right]); sm = shadowMasks[CellFace.Right]; gi = GIs[CellFace.Right]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } // cell face: z positive if (BlockManager.blocks[c12[x2, y, (z + 1) & Chunk.SIZE_Z_MINUS_ONE].index].isTransparent) { la = CalculateLighting(c22[ClipX(x2 + 1), y + 1, ClipZ(z2 + 1)].lightF, c12[x2, y + 1, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y, ClipZ(z2 + 1)].lightF, c12[x2, y, ClipZ(z2 + 1)].lightF); lb = CalculateLighting(c12[x2, y + 1, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y + 1, ClipZ(z2 + 1)].lightF, c12[x2, y, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y, ClipZ(z2 + 1)].lightF); lc = CalculateLighting(c12[x2, y, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y, ClipZ(z2 + 1)].lightF, c12[x2, y - 1, ClipZ(z2 + 1)].lightF, c02[ClipX(x2 - 1), y - 1, ClipZ(z2 + 1)].lightF); ld = CalculateLighting(c22[ClipX(x2 + 1), y, ClipZ(z2 + 1)].lightF, c12[x2, y, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y - 1, ClipZ(z2 + 1)].lightF, c12[x2, y - 1, ClipZ(z2 + 1)].lightF); ShadedVerticeQuad(new Vector3(x2 + 1, y + 1, z2 + 1), new Vector3(x2, y + 1, z2 + 1), new Vector3(x2, y, z2 + 1), new Vector3(x2 + 1, y, z2 + 1), la, lb, lc, ld); TexQuad(texCoord[CellFace.Front]); sm = shadowMasks[CellFace.Front]; gi = GIs[CellFace.Front]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } // cell face: z negative if (BlockManager.blocks[c10[x2, y, (z - 1) & Chunk.SIZE_Z_MINUS_ONE].index].isTransparent) { la = CalculateLighting(c10[x2, y + 1, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y + 1, ClipZ(z2 - 1)].lightF, c10[x2, y, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y, ClipZ(z2 - 1)].lightF); lb = CalculateLighting(c20[ClipX(x2 + 1), y + 1, ClipZ(z2 - 1)].lightF, c10[x2, y + 1, ClipZ(z2 - 1)].lightF, c20[ClipX(x2 + 1), y, ClipZ(z2 - 1)].lightF, c10[x2, y, ClipZ(z2 - 1)].lightF); lc = CalculateLighting(c20[ClipX(x2 + 1), y, ClipZ(z2 - 1)].lightF, c10[x2, y, ClipZ(z2 - 1)].lightF, c20[ClipX(x2 + 1), y - 1, ClipZ(z2 - 1)].lightF, c10[x2, y - 1, ClipZ(z2 - 1)].lightF); ld = CalculateLighting(c10[x2, y, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y, ClipZ(z2 - 1)].lightF, c10[x2, y - 1, ClipZ(z2 - 1)].lightF, c00[ClipX(x2 - 1), y - 1, ClipZ(z2 - 1)].lightF); ShadedVerticeQuad(new Vector3(x2, y + 1, z2), new Vector3(x2 + 1, y + 1, z2), new Vector3(x2 + 1, y, z2), new Vector3(x2, y, z2), la, lb, lc, ld); TexQuad(texCoord[CellFace.Back]); sm = shadowMasks[CellFace.Back]; gi = GIs[CellFace.Back]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } // cell face: y positive if (BlockManager.blocks[c11[x2, y + 1, z2].index].isTransparent) { la = CalculateLighting(c00[ClipX(x2 - 1), y + 1, ClipZ(z2 - 1)].lightF, c01[ClipX(x2 - 1), y + 1, z2].lightF, c11[x2, y + 1, z2].lightF, c10[x2, y + 1, ClipZ(z2 - 1)].lightF); lb = CalculateLighting(c01[ClipX(x2 - 1), y + 1, z2].lightF, c02[ClipX(x2 - 1), y + 1, ClipZ(z2 + 1)].lightF, c12[x2, y + 1, ClipZ(z2 + 1)].lightF, c11[x2, y + 1, z2].lightF); lc = CalculateLighting(c11[x2, y + 1, z2].lightF, c12[x2, y + 1, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y + 1, ClipZ(z2 + 1)].lightF, c21[ClipX(x2 + 1), y + 1, z2].lightF); ld = CalculateLighting(c10[x2, y + 1, ClipZ(z2 - 1)].lightF, c11[x2, y + 1, z2].lightF, c21[ClipX(x2 + 1), y + 1, z2].lightF, c20[ClipX(x2 + 1), y + 1, ClipZ(z2 - 1)].lightF); ShadedVerticeQuad(new Vector3(x2, y + 1, z2), new Vector3(x2, y + 1, z2 + 1), new Vector3(x2 + 1, y + 1, z2 + 1), new Vector3(x2 + 1, y + 1, z2), la, lb, lc, ld); TexQuad(texCoord[CellFace.Up]); sm = shadowMasks[CellFace.Up]; gi = GIs[CellFace.Up]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } // cell face: y negative if (BlockManager.blocks[c11[x2, y - 1, z2].index].isTransparent) { ld = CalculateLighting(c01[ClipX(x2 - 1), y - 1, z2].lightF, c02[ClipX(x2 - 1), y - 1, ClipZ(z2 + 1)].lightF, c12[x2, y - 1, ClipZ(z2 + 1)].lightF, c11[x2, y - 1, z2].lightF); la = CalculateLighting(c00[ClipX(x2 - 1), y - 1, ClipZ(z2 - 1)].lightF, c01[ClipX(x2 - 1), y - 1, z2].lightF, c11[x2, y - 1, z2].lightF, c10[x2, y - 1, ClipZ(z2 - 1)].lightF); lb = CalculateLighting(c10[x2, y - 1, ClipZ(z2 - 1)].lightF, c11[x2, y - 1, z2].lightF, c21[ClipX(x2 + 1), y - 1, z2].lightF, c20[ClipX(x2 + 1), y - 1, ClipZ(z2 - 1)].lightF); lc = CalculateLighting(c11[x2, y - 1, z2].lightF, c12[x2, y - 1, ClipZ(z2 + 1)].lightF, c22[ClipX(x2 + 1), y - 1, ClipZ(z2 + 1)].lightF, c21[ClipX(x2 + 1), y - 1, z2].lightF); ShadedVerticeQuad(new Vector3(x2, y, z2), new Vector3(x2 + 1, y, z2), new Vector3(x2 + 1, y, z2 + 1), new Vector3(x2, y, z2 + 1), la, lb, lc, ld); TexQuad(texCoord[CellFace.Down]); sm = shadowMasks[CellFace.Down]; gi = GIs[CellFace.Down]; ColorQuad( (ca * sm + gi) * la, (cb * sm + gi) * lb, (cc * sm + gi) * lc, (cd * sm + gi) * ld); } }
public void Execute() { var chunk = terrain.GetChunk(chunkx, chunkz); if (chunk.chunkState == Chunk.ChunkState.InvalidLighting) { int startx = chunkx << Chunk.CHUNK_X_SHIFT; int startz = chunkz << Chunk.CHUNK_Z_SHIFT; for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { bool isUnderground = false; int y = 127; while (y > 1) { var cell = chunk[x, y, z]; if (isUnderground) { cell.light = 0; chunk[x, y, z] = cell; } else { cell.light = LightSettings.GlobalLightLevel; chunk[x, y, z] = cell; lightUpdates.Push(new Vector3Int(x + startx, y, z + startz)); } if (!isUnderground && !BlockManager.blocks[chunk[x, y - 1, z].index].isTransparent) { isUnderground = true; var shift = chunk.GetShiftData(x, z); shift.maxHeight = y - 1; chunk.SetShiftData(x, z, shift); } y--; } } } } while (lightUpdates.Count > 0) { var pos = lightUpdates.Pop(); int light = terrain.GetCell(pos).light; if (light < 2) { continue; } Chunk c11 = terrain.ChunkWithBlock(pos.x, pos.y, pos.z); Chunk c21 = terrain.ChunkWithBlock(pos.x + 1, pos.y, pos.z); Chunk c01 = terrain.ChunkWithBlock(pos.x - 1, pos.y, pos.z); Chunk c12 = terrain.ChunkWithBlock(pos.x, pos.y, pos.z + 1); Chunk c10 = terrain.ChunkWithBlock(pos.x, pos.y, pos.z - 1); Chunk c02 = terrain.ChunkWithBlock(pos.x - 1, pos.y, pos.z + 1); Chunk c22 = terrain.ChunkWithBlock(pos.x + 1, pos.y, pos.z + 1); Chunk c00 = terrain.ChunkWithBlock(pos.x - 1, pos.y, pos.z - 1); Chunk c20 = terrain.ChunkWithBlock(pos.x + 1, pos.y, pos.z - 1); if (c21 != null) { ProcessCell(new Vector3Int(pos.x + 1, pos.y, pos.z), c21, light); } if (c01 != null) { ProcessCell(new Vector3Int(pos.x - 1, pos.y, pos.z), c01, light); } if (c12 != null) { ProcessCell(new Vector3Int(pos.x, pos.y, pos.z + 1), c12, light); } if (c10 != null) { ProcessCell(new Vector3Int(pos.x, pos.y, pos.z - 1), c10, light); } if (pos.y < 127) { ProcessCell(new Vector3Int(pos.x, pos.y + 1, pos.z), c11, light); } if (pos.y > 1) { ProcessCell(new Vector3Int(pos.x, pos.y - 1, pos.z), c11, light); } } }