Fixed negative chunks invisible

This commit is contained in:
max
2025-12-14 23:54:22 +01:00
parent a1cdd6b5de
commit 35ecc36bdb
7 changed files with 118 additions and 40 deletions

View File

@@ -48,6 +48,8 @@ namespace Voxel
public new void Tick()
{
_world.UpdateChunkLoading(Position);
previousPosition = Position;
float forwards = 0;

View File

@@ -14,8 +14,8 @@ internal class Program
Console.WriteLine("Generating map...");
int worldSizeX = 8;
int worldSizeY = 8;
int worldSizeX = 2;
int worldSizeY = 2;
float maxI = worldSizeX * worldSizeY;
int i = 0;

View File

@@ -61,11 +61,12 @@ namespace Voxel
if (_world == null) return;
int offset = 0;
foreach (Chunk chunk in _world.GetAllChunks())
{
ChunkMesh chunkMesh = chunk.GetChunkMesh();
if (chunkMesh.NeedsUpdate)
if (chunkMesh.NeedsUpdate) // always true
{
byte[] data = chunkMesh.GetPackedData();
GL.BufferSubData(BufferTarget.ShaderStorageBuffer, (IntPtr)offset * 8, chunkMesh.Size * 8, data);

View File

@@ -10,16 +10,23 @@ uniform vec3 cameraPosition;
void main()
{
float fogEnd = 512;
float fogStart = 32;
float dist = length(cameraPosition - fragPos);
float fogFactor = (fogEnd - dist) / (fogEnd - fogStart);
fogFactor = clamp(fogFactor, 0, 1);
vec4 fogColor = vec4(0.8,0.8,0.8,1);
vec4 texColor = texture(uTexture, fragUV) * lighting;
vec4 color = mix(fogColor, texColor, fogFactor);
FragColor = vec4(color.rgb, texColor.a);
// Use squared distance
vec3 delta = cameraPosition - fragPos;
float distSq = dot(delta, delta);
// Precomputed fog parameters
const float fogEndSq = 16384.0; // 128^2
const float fogStartSq = 1024.0; // 32^2
const float fogRangeInv = 1.0 / (fogEndSq - fogStartSq);
float fogFactor = (fogEndSq - distSq) * fogRangeInv;
fogFactor = clamp(fogFactor, 0.0, 1.0);
// Texture and lighting
vec4 texColor = texture(uTexture, fragUV);
texColor.rgb *= lighting;
// Fog blend
const vec3 fogColor = vec3(0.8, 0.8, 0.8);
FragColor = vec4(mix(fogColor, texColor.rgb, fogFactor), texColor.a);
}

View File

@@ -82,7 +82,7 @@ void main()
uint faceIndex = gl_VertexID / 6u;
uint vertIndex = gl_VertexID % 6u;
uint start = faceIndex * 2u; // 2 byte per face
uint start = faceIndex * 2u; // 2 uint per face
uint u0 = faces[start]; // data in uint 0
uint u1 = faces[start + 1]; // data in uint 1
@@ -95,7 +95,8 @@ void main()
uint texture = u1 & 0xFFu;
uint lightLevel = (u1 >> 8) & 0xFFu;
vec3 basePos = vec3(x + chunkX * 16, y, z + chunkY * 16);
vec3 basePos = vec3(x, y, z) + vec3(chunkX, 0, chunkY) * 16.0;
vec4 worldPos = vec4(basePos + offsets[facing][vertIndex], 1.0);
float light = float(lightLevel) / 255.0; // use later for caves and stuff

View File

@@ -90,7 +90,7 @@ namespace Voxel
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
CursorState = CursorState.Grabbed;
//VSync = VSyncMode.On;
VSync = VSyncMode.On;
Camera.UpdateSize(Width, Height);
}

111
World.cs
View File

@@ -8,6 +8,9 @@ namespace Voxel
{
private Dictionary<(int, int), Chunk> _chunks;
private (int x, int z) _lastCenter = (0, 0);
private int _loadDistance = 4;
private static readonly Dictionary<Orientation, (int x, int y)> _neighborOffsets = new()
{
{ Orientation.West, (1, 0) },
@@ -33,6 +36,7 @@ namespace Voxel
UpdateNeighboringChunks(chunk);
chunk.UpdateChunkMesh();
Renderer.MarkBuffersDirty();
}
public void RemoveChunk(int chunkX, int chunkZ)
@@ -52,6 +56,63 @@ namespace Voxel
}
}
public new void UpdateChunkLoading(Vector3 playerPosition)
{
int centerX = (int)Math.Floor(playerPosition.X / Chunk.Size);
int centerZ = (int)Math.Floor(playerPosition.Z / Chunk.Size);
// Quick check - skip if still in same chunk
if (centerX == _lastCenter.x && centerZ == _lastCenter.z)
return;
_lastCenter = (centerX, centerZ);
// Calculate bounds
int minX = centerX - _loadDistance;
int maxX = centerX + _loadDistance;
int minZ = centerZ - _loadDistance;
int maxZ = centerZ + _loadDistance;
// Unload chunks outside range
UnloadDistantChunks(minX, maxX, minZ, maxZ);
// Load chunks inside range
LoadChunksInRange(minX, maxX, minZ, maxZ);
}
private void UnloadDistantChunks(int minX, int maxX, int minZ, int maxZ)
{
var chunksToRemove = new List<(int, int)>();
foreach (var (chunkX, chunkZ) in _chunks.Keys)
{
if (chunkX < minX || chunkX > maxX || chunkZ < minZ || chunkZ > maxZ)
{
chunksToRemove.Add((chunkX, chunkZ));
}
}
foreach (var chunkPos in chunksToRemove)
{
RemoveChunk(chunkPos.Item1, chunkPos.Item2);
}
}
private void LoadChunksInRange(int minX, int maxX, int minZ, int maxZ)
{
for (int x = minX; x <= maxX; x++)
{
for (int z = minZ; z <= maxZ; z++)
{
if (!_chunks.ContainsKey((x, z)))
{
Chunk chunk = new Chunk(x, z);
AddChunk(chunk);
}
}
}
}
public void UpdateNeighboringChunks(Chunk chunk)
{
chunk.Neighbors[Orientation.West] = null;
@@ -87,39 +148,21 @@ namespace Voxel
public Blocks GetBlock(int worldX, int worldY, int worldZ)
{
int chunkX = worldX / Chunk.Size;
int chunkZ = worldZ / Chunk.Size;
var (chunkX, chunkZ, localX, localZ) = WorldToChunkCoords(worldX, worldZ);
Chunk chunk = GetChunk(chunkX, chunkZ);
if (chunk == null) return 0; // air if chunk not loaded
int localX = worldX % Chunk.Size;
int localZ = worldZ % Chunk.Size;
return chunk.GetBlock(localX, worldY, localZ);
}
List<Orientation> GetEdgeOrientations(int localX, int localZ, int size)
{
var orientations = new List<Orientation>();
if (localX == size - 1) orientations.Add(Orientation.West);
if (localX == 0) orientations.Add(Orientation.East);
if (localZ == size - 1) orientations.Add(Orientation.North);
if (localZ == 0) orientations.Add(Orientation.South);
return orientations;
}
public void SetBlock(int worldX, int worldY, int worldZ, Blocks block)
{
int chunkX = worldX / Chunk.Size;
int chunkZ = worldZ / Chunk.Size;
var (chunkX, chunkZ, localX, localZ) = WorldToChunkCoords(worldX, worldZ);
Chunk chunk = GetChunk(chunkX, chunkZ);
if (chunk == null) return;
int localX = worldX % Chunk.Size;
int localZ = worldZ % Chunk.Size;
chunk.SetBlock(localX, worldY, localZ, block);
if (block == Blocks.Air && ((localX == Chunk.Size - 1 || localX == 0) || (localZ == Chunk.Size - 1 || localZ == 0)))
@@ -134,6 +177,30 @@ namespace Voxel
}
}
public static (int chunkX, int chunkZ, int localX, int localZ) WorldToChunkCoords(int worldX, int worldZ)
{
int chunkX = worldX >= 0 ? worldX / Chunk.Size : (worldX + 1) / Chunk.Size - 1;
int chunkZ = worldZ >= 0 ? worldZ / Chunk.Size : (worldZ + 1) / Chunk.Size - 1;
int localX = ((worldX % Chunk.Size) + Chunk.Size) % Chunk.Size;
int localZ = ((worldZ % Chunk.Size) + Chunk.Size) % Chunk.Size;
return (chunkX, chunkZ, localX, localZ);
}
List<Orientation> GetEdgeOrientations(int localX, int localZ, int size)
{
var orientations = new List<Orientation>();
if (localX == size - 1) orientations.Add(Orientation.West);
if (localX == 0) orientations.Add(Orientation.East);
if (localZ == size - 1) orientations.Add(Orientation.North);
if (localZ == 0) orientations.Add(Orientation.South);
return orientations;
}
public IEnumerable<(Orientation orientation, Chunk neighbor)> GetChunkNeighbors(Chunk chunk)
{
int chunkX = chunk.X;