Voxeliq currently uses an advanced optimization to improve rendering performance, in simple worlds while building the mesh for a chunk, instead of building the complete mesh for the chunk, it only builds it partially (basically it doesn't include blocks in the mesh where user can't seem them).
Check this graphic;
![chunk-meshes](https://camo.githubusercontent.com/59bf88c0228fb32b26c26c5a7c09ebc5103d8c7b347dd75824ceea81a4570ad9/687474703a2f2f692e696d6775722e636f6d2f4761646a6f2e706e67)
So lets say that a chunk may had landscape generated around y=50 ~ y=55.
- So with out the optimization, the mesh would contain all the blocks from y=0 to to y=55
- which means more blocks in the mesh = more polygons in the mesh = lower rendering performance.
So the ideas is that, user will not able to see blocks below the lowest-solid-block-index(y) in chunk.
![chunk-meshes](https://camo.githubusercontent.com/a868498965f33c1213af7978195b9ed5117cac3ebb0b2333cf273ac1445b1b1c/687474703a2f2f692e696d6775722e636f6d2f56376133332e706e67)
As in the screenshot above, users will not be able to see blocks below the [chunk's lowest block index - 1](marked with purple).
And the optimization arrives here, where we only build the mesh between [chunks highest block index + 1] to [chunks lowest block index -1].
This optimization is all good and improves the rendering performance a lot but with a given drawback; with every set-block operation, chunk's highest block index and lowest block index values have to be updated.
In the current state of the engine, this is done in landscape-generation after every block-set operation;
air (empty) blocks
BlockStorage.Blocks[offset + y] = new Block(BlockType.None);
if (chunk.LowestEmptyBlockOffset > y) chunk.LowestEmptyBlockOffset = (byte)y;
---
(solid blocks)
BlockStorage.Blocks[offset + y] = new Block(BlockType.Dirt);
if (y > chunk.HighestSolidBlockOffset) chunk.HighestSolidBlockOffset = (byte)y;
The problem is that this is an engine and forcing game-developers for so, will increase the entry barrier of engine higher and will make things complex.
A solution is that using the available SetBlock methods which can find the chunk block belongs to and do the calculation on it's own.
public static void SetBlockAt(int x, int y, int z, Block block)
The problem is that setting blocks in a block-engine is an operation used millions of times. The current method we use in first code snippet is automatic (or close enough being atomic at least in our context - as it just sets a byte value in our Flatten Block Storage array).
The latter solution in second snippet means calling that SetBlockAt() functions over and over millions of times, which for sure will decrease the performance a lot - here's a proof of concept test; http://www.dotnetperls.com/inline-optimization
So I've been looking for possible solutions and here's what I've came up with;
Statement Lamdas
As I've discussed it here and they maybe a solution but I'm not sure yet, will check it further & profile.
Conventional way:
-----------------
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: ldarg.2
L_0004: ldarg.3
L_0005: call int32 VolumetricStudios.VoxeliqGame.Chunks.BlockCache::BlockIndexByRelativePosition(class VolumetricStudios.VoxeliqGame.Chunks.Chunk,
uint8, uint8, uint8)
Statement Lambdas:
------------------
L_0000: nop
L_0001: ldsfld class [mscorlib]System.Func5<class VolumetricStudios.VoxeliqGame.Chunks.Chunk, uint8, uint8, uint8,
int32> VolumetricStudios.VoxeliqGame.Chunks.BlockCache::BlockIndexByRelativePosition3
L_0006: ldarg.0
L_0007: ldarg.1
L_0008: ldarg.2
L_0009: ldarg.3
L_000a: callvirt instance !4 [mscorlib]System.Func`5<class VolumetricStudios.VoxeliqGame.Chunks.Chunk, uint8, uint8, uint8, int32>::Invoke(!0, !1, !2, !3)
The second solution is MethodImplOptions.AggressiveInlining that was introduced with .net framework 4.5. But I'm not sure if we'll be able to change our engine projects framework version to 4.5. Will also try that.
I'm looking for other possible solutions.
Interesting reads on the topic;