Skip to content

Commit

Permalink
fix chunking
Browse files Browse the repository at this point in the history
  • Loading branch information
Pannoniae committed Jul 31, 2024
1 parent 6fc0cbf commit f8efc0a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 55 deletions.
1 change: 1 addition & 0 deletions BlockGame.sln.DotSettings.user
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARgba32_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F26350e1c36be2f1714c4e49a169d226daca646a6fa6da1f89b5fad2931043_003FRgba32_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARgba32_002EPixelOperations_002EGenerated_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F3c72d8c39213bfbec86e5496ee36cb45c31e8f6b747e562fa30dbdb51942_003FRgba32_002EPixelOperations_002EGenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AScalar_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F56_003Fd747cb09_003FScalar_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector128_005F1_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F87158aabd3c3a6992241aea5d45ad2139e02d325be495ab557ba61fd8a986_003FVector128_005F1_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector2_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe22c0dd9a2174ddd9f8050156d17fadcb2c800_003Fe3_003F81c2c9b6_003FVector2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F57_003F1d92b6f3_003FVector3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3D_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F93_003F3bc9f62f_003FVector3D_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
Expand Down
121 changes: 66 additions & 55 deletions src/render/SubChunkRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace BlockGame;

public sealed class SubChunkRenderer : IDisposable {
public SubChunk subChunk;
private readonly SubChunk subChunk;

// we need it here because completely full chunks are also empty of any rendering
private bool hasRenderOpaque;
Expand All @@ -33,12 +33,12 @@ public sealed class SubChunkRenderer : IDisposable {

// actually we don't need a list, regular arrays will do because it's only a few megs of space and it's shared
// in the future when we want multithreaded meshing, we can just allocate like 4-8 of them and it will still be in the ballpark of 10MB
private static List<BlockVertexPacked> chunkVertices = new(2048);
private static List<ushort> chunkIndices = new(2048);
private static readonly List<BlockVertexPacked> chunkVertices = new(2048);
private static readonly List<ushort> chunkIndices = new(2048);
// YZX again
private static ushort[] neighbours = new ushort[Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX];
private static byte[] neighbourLights = new byte[Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX];
private static ArrayBlockData?[] neighbourSections = new ArrayBlockData?[27];
private static readonly ushort[] neighbours = new ushort[Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX];
private static readonly byte[] neighbourLights = new byte[Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX * Chunk.CHUNKSIZEEX];
private static readonly ArrayBlockData?[] neighbourSections = new ArrayBlockData?[27];

private static Stopwatch sw = new Stopwatch();

Expand Down Expand Up @@ -153,7 +153,7 @@ public void Dispose() {
/// TODO store the number of blocks in the chunksection and only allocate the vertex list up to that length
/// </summary>
public void meshChunk() {
//sw.Restart();
sw.Restart();
if (subChunk.world.renderer.fastChunkSwitch) {
vao?.Dispose();
vao = new ExtremelySharedBlockVAO(subChunk.world.renderer.chunkVAO);
Expand Down Expand Up @@ -207,7 +207,7 @@ public void meshChunk() {
var finalVertices = CollectionsMarshal.AsSpan(chunkVertices);
var finalIndices = CollectionsMarshal.AsSpan(chunkIndices);
vao.upload(finalVertices, finalIndices);
//Console.Out.WriteLine($"PartMeshing1.2: {sw.Elapsed.TotalMicroseconds}us {chunkIndices.Count}");
Console.Out.WriteLine($"PartMeshing1.2: {sw.Elapsed.TotalMicroseconds}us {chunkIndices.Count}");
}
else {
hasRenderOpaque = false;
Expand Down Expand Up @@ -238,8 +238,11 @@ public void meshChunk() {
}
}
//}
//Console.Out.WriteLine($"Meshing: {sw.Elapsed.TotalMicroseconds}us");
//sw.Stop();
Console.Out.WriteLine($"Meshing: {sw.Elapsed.TotalMicroseconds}us {chunkIndices.Count}");
//if (!subChunk.isEmpty && !hasRenderOpaque && !hasRenderTranslucent) {
// Console.Out.WriteLine($"CHUNKDATA: {subChunk.blocks.blockCount} {subChunk.blocks.isFull()}");
//}
sw.Stop();
}


Expand Down Expand Up @@ -361,7 +364,8 @@ private void setupNeighbours() {
// set neighbours array element to block
blocksArrayRef = bl;
// if neighbour is not solid, we still have to mesh this chunk even though all of it is solid
if (hasOnlySolid && !Blocks.isFullBlock(bl)) {
// NOTE: check if it's loaded (if it isn't loaded we don't give a shit about it)
if (!Blocks.isFullBlock(bl) && nn) {
hasOnlySolid = false;
}

Expand Down Expand Up @@ -474,7 +478,12 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
// this is garbage but we'll deal with it later

// one AO value fits on 2 bits so the whole thing fits in a byte
byte ao = 0;
FourBytes ao;
ao.Whole = 0;
Unsafe.SkipInit(out ao.First);
Unsafe.SkipInit(out ao.Second);
Unsafe.SkipInit(out ao.Third);
Unsafe.SkipInit(out ao.Fourth);

// setup neighbour data
// if all 6 neighbours are solid, we don't even need to bother iterating the faces
Expand Down Expand Up @@ -556,13 +565,13 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
// AO requires smooth lighting. Otherwise don't need to deal with sampling any of this
if ((settings & 3) != 0) {
// ox, oy, oz
ushort o;
FourBytes o;
// need to store 9 sbytes so it's a 16-element vector
// lx, ly, lz, lo
// we need 12 bytes
Vector128<byte> l;

ao = 0;
ao.Whole = 0;


//for (int j = 0; j < 4; j++) {
Expand All @@ -572,7 +581,6 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
// load the vector with the offsets
// we need 12 offsets
var offsets = Vector256.LoadUnsafe(ref Unsafe.Add(ref offsetArray, (int)dir * 12));

l = Vector128.Create(
Unsafe.Add(ref lightRef, offsets[0]),
Unsafe.Add(ref lightRef, offsets[1]),
Expand All @@ -591,37 +599,40 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
Unsafe.Add(ref lightRef, offsets[11]),
lba[(byte)dir]);

o = (ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[0]))) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[1]))) << 1) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[2]))) << 2) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[3]))) << 3) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[4]))) << 4) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[5]))) << 5) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[6]))) << 6) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[7]))) << 7) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[8]))) << 8) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[9]))) << 9) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[10]))) << 10) |
(ushort)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[11]))) << 11));
o.First = (byte)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[0]))) |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[1]))) << 1 |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[2]))) << 2);

o.Second = (byte)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[3]))) |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[4]))) << 1 |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[5]))) << 2);

o.Third = (byte)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[6]))) |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[7]))) << 1 |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[8]))) << 2);

o.Fourth = (byte)(Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[9]))) |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[10]))) << 1 |
Unsafe.BitCast<bool, byte>(Blocks.isFullBlock(
Unsafe.Add(ref neighbourRef, offsets[11]))) << 2);

// only apply AO if enabled
if ((settings & SETTING_AO) != 0 && !facesRef.noAO) {
ao |= (byte)((o & 3) == 3 ? 3 : byte.PopCount((byte)(o & 7)));
ao |= (byte)((((o >> 3) & 3) == 3 ? 3 : byte.PopCount((byte)((o >> 3) & 7))) << 2);
ao |= (byte)((((o >> 6) & 3) == 3 ? 3 : byte.PopCount((byte)((o >> 6) & 7))) << 4);
ao |= (byte)((((o >> 9) & 3) == 3 ? 3 : byte.PopCount((byte)((o >> 9) & 7))) << 6);
ao.First = (byte)(o.First == 3 ? 3 : byte.PopCount((byte)(o.First & 7)));
ao.Second = (byte)((o.Second & 3) == 3 ? 3 : byte.PopCount((byte)(o.Second & 7)));
ao.Third = (byte)((o.Third & 3) == 3 ? 3 : byte.PopCount((byte)(o.Third & 7)));
ao.Fourth = (byte)((o.Fourth & 3) == 3 ? 3 : byte.PopCount((byte)(o.Fourth & 7)));
}

// if face is noAO, don't average....
Expand All @@ -634,28 +645,28 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
// split light and reassemble it again
light.First = (byte)(
average((n[0] >> 4) & 0x0F0F0F0F,
(byte)(o & 7))
(byte)(o.First & 7))
<< 4 |
average(n[0] & 0x0F0F0F0F,
(byte)(o & 7)));
(byte)(o.First & 7)));
light.Second = (byte)(
average((n[1] >> 4) & 0x0F0F0F0F,
(byte)((o >> 3) & 7))
(byte)(o.Second & 7))
<< 4 |
average(n[1] & 0x0F0F0F0F,
(byte)((o >> 3) & 7)));
(byte)(o.Second & 7)));
light.Third = (byte)(
average((n[2] >> 4) & 0x0F0F0F0F,
(byte)((o >> 6) & 7))
(byte)(o.Third & 7))
<< 4 |
average(n[2] & 0x0F0F0F0F,
(byte)((o >> 6) & 7)));
(byte)(o.Third & 7)));
light.Fourth = (byte)(
average((n[3] >> 4) & 0x0F0F0F0F,
(byte)((o >> 9) & 7))
(byte)(o.Fourth & 7))
<< 4 |
average(n[3] & 0x0F0F0F0F,
(byte)((o >> 9) & 7)));
(byte)(o.Fourth & 7)));
}
//}
}
Expand Down Expand Up @@ -700,31 +711,31 @@ static byte getLightFromCacheUnsafe(ref byte arrayBase, int x, int y, int z) {
vertex.z = (ushort)vec[2];
vertex.u = (ushort)tex[0];
vertex.v = (ushort)tex[1];
vertex.d = Block.packData((byte)dir, (byte)(ao & 0x3), light.First);
vertex.d = Block.packData((byte)dir, ao.First, light.First);

vertex = ref tempVertices[1];
vertex.x = (ushort)vec[3];
vertex.y = (ushort)vec[4];
vertex.z = (ushort)vec[5];
vertex.u = (ushort)tex[0];
vertex.v = (ushort)tex[3];
vertex.d = Block.packData((byte)dir, (byte)(ao >> 2 & 0x3), light.Second);
vertex.d = Block.packData((byte)dir, ao.Second, light.Second);

vertex = ref tempVertices[2];
vertex.x = (ushort)vec[6];
vertex.y = (ushort)vec[7];
vertex.z = (ushort)vec2[0];
vertex.u = (ushort)tex[2];
vertex.v = (ushort)tex[3];
vertex.d = Block.packData((byte)dir, (byte)(ao >> 4 & 0x3), light.Third);
vertex.d = Block.packData((byte)dir, ao.Third, light.Third);

vertex = ref tempVertices[3];
vertex.x = (ushort)vec2[1];
vertex.y = (ushort)vec2[2];
vertex.z = (ushort)vec2[3];
vertex.u = (ushort)tex[2];
vertex.v = (ushort)tex[1];
vertex.d = Block.packData((byte)dir, (byte)(ao >> 6), light.Fourth);
vertex.d = Block.packData((byte)dir, ao.Fourth, light.Fourth);
chunkVertices.AddRange(tempVertices);
//cv += 4;

Expand Down

0 comments on commit f8efc0a

Please sign in to comment.